Kubernetes (K8S for short) has become the best tool for containerization since its release. This article uses a simple case to talk about how to deploy a container to a K8S cluster. The code and containers required in this article are on GITHUB. If you need to build a K8S cluster, you can build it through minikube or use the K8S cluster provided by Docker for Desktop

1 Create the simplest Deployment

Just a couple of concepts

  • Pod: a core concept of K8S. It is a collection of one or more Containers. Containers in a POD share storage and network. K8s supports a variety of Contianers, but docker Containers are by far the most common. Our application ultimately exists in the form of pod, which is the smallest unit of K8S scheduling.
  • ReplicaSet: also a resource in K8S, it manages multiple copies of a POD. In order to ensure high availability, we usually deploy multiple copies of pod to avoid single points of failure. If replicaSet manages a pod that dies, it requests a new pod to meet the specified number of replicas. K8s also has a ReplicaionController that also controls pod replicas, but ReplicaSet supports pod tags better than ReplicaionController, which is currently used
  • Deployment: is a more high-level resource. After creating a Deployment, a ReplicaSet is created, which then creates the expected number of PODS. Deployment can manage ReplicaSet versions for easy rollback. In production, it is common to create a Deployment

Let’s start with a simple Web application, simple-Web, and package it as docker image Simple-Web :1.0. So if you go to /index for your Web application, it will print the name of your Web application, and if you go to /health, it will return “OK”.

> curl http://ip:8080/index
  web site name is [demo-web]
> curl http://ip:8080/health
  OK
Copy the code

Define a deployment.yml as follows

kubectl create -f deployment.yml

➜ ~ k get deploy NAME READY up-date AVAILABLE AGE simple-web 1/1 1 1 2d4h ➜ ~ k get RS NAME DESIRED CURRENT READY AGE Siml-web-6bdf7b4d84 1 1 47h ➜ ~ k get Pods NAME READY STATUS RESTARTS AGE siml-web-6bdf7b4d84-p7jKP 1/1 Running 0  47hCopy the code

Curl = kubectl exec = kubectl exec = kubectl exec

➜  ~ k exec  simple-web-6bdf7b4d84-p7jkp --  curl -s http://localhost:8080/index
web site name is [demo-web]
Copy the code

2 Access pod using service

2.1 the port – forward

Just by creating a Deployment, we can access our own Web services only within the POD, not externally or between the Pods. Kubectl port-forward
can proxy a port from the host to a pod in the container, allowing us to access the Web service from the host

➜  ~ k port-forward simple-web-6bdf7b4d84-p7jkp 8889:8080
Forwarding from 127.0.0.1:8889 -> 8080
Forwarding from [::1]:8889 -> 8080

➜  ~ curl 127.0.0.1:8889/index
web site name is [demo-web]
Copy the code

2.2 the service

But when we have multiple copies of pods, it is impossible to specify ports for each pod proxy, and port-forward does not resolve service discovery between pods. At this point we need Service to provide routing

To create a

apiVersion: v1
kind: Service
metadata:
  name: simple-web
spec:
  selector:
    app: simple-web
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080
Copy the code

Here we need to fill in the selector label for the pod defined in the Deployment

➜ ~ k get SVC NAME TYPE cluster-ip external-ip PORT(S) AGE simple-web ClusterIP 10.96.156.194 < None > 80/TCP 2d4hCopy the code

We create a service called simple-Web, and you can see that K8S assigns a clusterIP and maps port 80 of this IP to port 8080 of pod

➜  ~ curl 10.96.156.194/index
web site name is [demo-web]
Copy the code

In addition to IP access, we can also access using serivce

➜  ~ k exec simple-web-6bdf7b4d84-2kzxx -- curl http://simple-web/index
web site name is [demo-web]
Copy the code

2.3 nodeport

With ClusterIP we can only access pods within the K8S cluster. If we want to access pods from outside, we can define a Service of NodePort Type

apiVersion: v1
kind: Service
metadata:
  name: simple-web
spec:
  type: NodePort
  selector:
    app: simple-web
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080
      nodePort: 32100
Copy the code

Nodeport is the host IP address for the pod web Service. Nodeport is the host IP address for the pod web Service. Nodeport is the host IP address for the pod web Service

3 Volume

Volume provides a means for data interaction between PODS ‘containers and between containers and hosts or other storage devices. The k8S Volume has many types. The following uses EmptyDir as an example to see how to use a Volume. We mount the Web application log to EmptyDir, configured as follows

apiVersion: apps/v1 kind: Deployment metadata: name: simple-web spec: replicas: 1 selector: matchLabels: app: simple-web template: metadata: labels: app: simple-web spec: containers: - name: simple-web image: Simple-web :1.0 volumeMounts: -name: app-log mountPath: /app/logs volumes: -name: app-log emptyDir: {}Copy the code

We can find emptyDir path on the host, the default is/var/lib/kubelet/pods/PODUID/volumes/kubernetes IO ~ empty – dir/VOLUMENAME

➜ ~ k get the pods simple - web - 6 bdf7b4d84-2 KZXX -o yaml | grep uid uid: 437573 BC - 7398-4004-89 ac - 0 d268e986c74 uid: be609483-ed6d-427f-b277-81931cc9eb60Copy the code

Be609483-ed6d-427f-b277-81931cc9eb60 is the POD uid. For example, the log on our host can be collected by fileBeat

4 configmap

If we want to change the behavior of an application by changing its configuration after deploying it to POD, we don’t want to have to repackage an image, so we need to separate out the configuration file, and ConfigMap can help us do that

apiVersion: v1
kind: ConfigMap
metadata:
  name: simple-web-config
data:
  app-config: |-
    app.name=web-name-from-config-web
Copy the code

Then modify the Deployment as follows

apiVersion: apps/v1 kind: Deployment metadata: name: simple-web spec: replicas: 1 selector: matchLabels: app: simple-web template: metadata: labels: app: simple-web spec: containers: - name: simple-web image: Simple-web :1.0 volumeMounts: -name: app-log-vol mountPath: /app/ logs-name: config-vol mountPath: /app/conf/application.properties subPath: application.properties volumes: - name: app-log-vol emptyDir: {} - name: config-vol configMap: name: simple-web-config items: - key: app-config path: application.propertiesCopy the code

We put the configuration in the configmap mounted to the/app/conf/application. The properties, We applied the startup script reads the configuration file Java jar – simple – web. Jar — spring. Config. The location = / app/conf/application. The properties, in this way, We separate the configuration file from the application. After modifying the configuration file, application.properties has been updated, but since the Java application does not reload the configuration file, you need to restart the POD

5 LiVENESS, Readiness, and POD Resources

5.1 liveness and readiness

How does K8S know that a POD is no longer available? We need to define a HEALTH CHECK LIP that K8S periodically requests to determine whether the service is healthy. Readiness Similarly, determine whether a POD is ready to provide services through the definition of Readiness

5.2 the resources

K8s provides a way to limit the amount of resources a Container can use. Resources.requests defines how many resources are required for K8S to schedule pods to well-resourced nodes, and resources.limits limits the total amount of resources that containers can use. See Kubernetes Container Resource Requirements

apiVersion: apps/v1 kind: Deployment metadata: name: simple-web spec: replicas: 1 selector: matchLabels: app: simple-web template: metadata: labels: app: simple-web spec: containers: - name: simple-web image: Simple - Web :1.0 livenessProbe: httpGet: path: /health port: 8080 readinessProbe: httpGet: path: /health port: 8080 volumeMounts: - name: app-log-vol mountPath: /app/logs - name: config-vol mountPath: /app/conf/application.properties subPath: application.properties resources: requests: memory: 2048Mi cpu: 2 limits: memory: 2048Mi cpu: 2 volumes: - name: app-log-vol emptyDir: {} - name: config-vol configMap: name: simple-web-config items: - key: app-config path: application.propertiesCopy the code

6 Others to be added, pause containers, dashboards