You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

133 lines
4.8 KiB

  1. # Kubernetes 101
  2. ## Docker vs. Kubernetes
  3. Docker helps you package applications into images, and execute them in containers. Kubernetes is a robust platform for containerized applications. It abstracts away the underlying network infrastructure and hardware required to run them, simplifying their deployment, scaling, and management.
  4. ## Kubernetes from the container up
  5. ### Pods
  6. The basic unit of a Kubernetes deployment is the **Pod**. A Pod encapsulates one or more containers. For example, the `basket` Pod specifies two containers:
  7. >`deployments.yaml`
  8. >
  9. >The first container runs the `eshop/basket.api` image:
  10. >```yaml
  11. >spec:
  12. > containers:
  13. > - name: basket
  14. > image: eshop/basket.api
  15. > env:
  16. > - name: ConnectionString
  17. > value: 127.0.0.1
  18. >```
  19. >Note the `ConnectionString` environment variable: containers within a Pod are networked via `localhost`. The second container runs the `redis` image:
  20. >```yaml
  21. >- name: basket-data
  22. > image: redis:3.2-alpine
  23. > ports:
  24. > - containerPort: 6379
  25. >```
  26. Placing `basket` and `basket-data` in the same Pod is reasonable here because the former requires the latter, and owns all its data. If we wanted to scale the service, however, it would be better to place the containers in separate Pods because the basket API and redis scale at different rates.
  27. If the containers were in separate Pods, they would no longer be able to communicate via `localhost`; a **Service** would be required.
  28. ### Services
  29. Services expose Pods to external networks. For example, the `basket` Service exposes Pods with labels `app=eshop` and `component=basket` to the cluster at large:
  30. >`services.yaml`
  31. >```yaml
  32. >kind: Service
  33. >metadata:
  34. > ...
  35. > name: basket
  36. >spec:
  37. > ports:
  38. > - port: 80
  39. > selector:
  40. > app: eshop
  41. > component: basket
  42. >```
  43. Kubernetes's built-in DNS service resolves Service names to cluster-internal IP addresses. This allows the nginx frontend to proxy connections to the app's microservices by name:
  44. >`nginx.conf`
  45. >```
  46. >location /basket-api {
  47. > proxy_pass http://basket;
  48. >```
  49. The frontend Pod is different in that it needs to be exposed outside the cluster. This is accomplished with another Service:
  50. >`frontend.yaml`
  51. >```yaml
  52. >spec:
  53. > ports:
  54. > - port: 80
  55. > targetPort: 8080
  56. > selector:
  57. > app: eshop
  58. > component: frontend
  59. > type: LoadBalancer
  60. >```
  61. `type: LoadBalancer` tells Kubernetes to expose the Service behind a load balancer appropriate for the cluster's platform. For Azure Container Service, this creates an Azure load balancer rule with a public IP.
  62. ### Deployments
  63. Kubernetes uses Pods to organize containers, and Services to network them. It uses **Deployments** to organize creating, and modifying, Pods. A Deployment describes a state of one or more Pods. When a Deployment is created or modified, Kubernetes attempts to realize that state.
  64. The Deployments in this project are basic. Still, `deploy.ps1` shows some more advanced Deployment capabilities. For example, Deployments can be paused. Each Deployment of this app is paused at creation:
  65. >`deployments.yaml`
  66. >```yaml
  67. >kind: Deployment
  68. >spec:
  69. > paused: true
  70. >```
  71. This allows the deployment script to change images before Kubernetes creates the Pods:
  72. >`deploy.ps1`
  73. >```powershell
  74. >kubectl set image -f deployments.yaml basket=$registry/basket.api ...
  75. >kubectl rollout resume -f deployments.yaml
  76. >```
  77. ### ConfigMaps
  78. A **ConfigMap** is a collection of key/value pairs commonly used to provide configuration information to Pods. The deployment script uses one to store the frontend's configuration:
  79. >`deploy.ps1`
  80. >```
  81. >kubectl create configmap config-files from-file=nginx-conf=nginx.conf
  82. >```
  83. This creates a ConfigMap named `config-files` with key `nginx-conf` whose value is the content of nginx.conf. The frontend Pod mounts that value as `/etc/nginx/nginx.conf`:
  84. >`frontend.yaml`
  85. >```yaml
  86. >spec:
  87. > containers:
  88. > - name: nginx
  89. > ...
  90. > volumeMounts:
  91. > - name: config
  92. > mountPath: /etc/nginx
  93. > volumes:
  94. > - name: config
  95. > configMap:
  96. > name: config-files
  97. > items:
  98. > - key: nginx-conf
  99. > path: nginx.conf
  100. >```
  101. This facilitates rapid iteration better than other techniques, e.g. building an image to bake in configuration.
  102. The script also stores public URLs for the app's components in a ConfigMap:
  103. >`deploy.ps1`
  104. >```powershell
  105. >kubectl create configmap urls --from-literal=BasketUrl=http://$($frontendUrl)/basket-api ...
  106. >```
  107. >Here's how the `webspa` Deployment uses it:
  108. >
  109. >`deployments.yaml`
  110. >```yaml
  111. >spec:
  112. > containers:
  113. > - name: webspa
  114. > ...
  115. > env:
  116. > ...
  117. > - name: BasketUrl
  118. > valueFrom:
  119. > configMapKeyRef:
  120. > name: urls
  121. > key: BasketUrl
  122. >```
  123. ### Further reading
  124. * [Kubernetes Concepts](https://kubernetes.io/docs/concepts/)
  125. * [kubectl for Docker Users](https://kubernetes.io/docs/user-guide/docker-cli-to-kubectl/)
  126. * [Kubernetes API reference](https://kubernetes.io/docs/api-reference/v1.5/)