学习 Kubernetes 基础知识

参考资料

https://kubernetes.io/docs/tutorials/kubernetes-basics/

创建集群

通过运行minikube version命令,检查是否已正确安装:

$ minikube version
minikube version: v1.10.1
commit: 63ab801ac27e5742ae442ce36dff7877dcccb278

通过运行minikube start命令来启动集群:

$ minikube start
* minikube v1.10.1 on Debian 10.2
* Using the docker driver based on existing profile
* Starting control plane node minikube in cluster minikube
* Restarting existing docker container for "minikube" ...
* Preparing Kubernetes v1.18.2 on Docker 19.03.2 ...
  - kubeadm.pod-network-cidr=10.244.0.0/16
* Enabled addons: dashboard, default-storageclass, storage-provisioner
* Done! kubectl is now configured to use "minikube"

检查是否安装了kubectl,运行kubectl version命令:

$ kubectl version
Client Version: version.Info{Major:"1", Minor:"18", GitVersion:"v1.18.2", GitCommit:"52c56ce7a8272c798dbc29846288d7cd9fbae032", GitTreeState:"clean", BuildDate:"2020-04-16T11:56:40Z", GoVersion:"go1.13.9", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"18", GitVersion:"v1.18.2", GitCommit:"52c56ce7a8272c798dbc29846288d7cd9fbae032", GitTreeState:"clean", BuildDate:"2020-04-16T11:48:36Z", GoVersion:"go1.13.9", Compiler:"gc", Platform:"linux/amd64"}

查看集群的详细信息

$ kubectl cluster-info dump // 集群详细信息
$ kubectl cluster-info // 查看集群信息
Kubernetes master is running at https://172.17.0.2:8443
KubeDNS is running at https://172.17.0.2:8443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.

查看集群中的节点

$ kubectl get nodes
NAME       STATUS   ROLES    AGE   VERSION
minikube   Ready    master   14h   v1.18.2

部署应用

部署应用

部署我们的第一个应用程序

$ kubectl create deployment kubernetes-bootcamp --image=gcr.io/google-samples/kubernetes-bootcamp:v1
deployment.apps/kubernetes-bootcamp created

列出部署的应用程序

$ kubectl get deployments
NAME                  READY   UP-TO-DATE   AVAILABLE   AGE
kubernetes-bootcamp   1/1     1            1           73s

在另一个终端中运行代理,该代理会将通信转发到群集范围的专用网络中。

可以通过按Ctrl-C终止代理,并且在运行时不显示任何输出。

$ kubectl proxy
Starting to serve on 127.0.0.1:8001

可以使用curl命令直接通过API查询版本:

$ curl http://localhost:8001/version
{
  "major": "1",
  "minor": "18",
  "gitVersion": "v1.18.2",
  "gitCommit": "52c56ce7a8272c798dbc29846288d7cd9fbae032",
  "gitTreeState": "clean",
  "buildDate": "2020-04-16T11:48:36Z",
  "goVersion": "go1.13.9",
  "compiler": "gc",
  "platform": "linux/amd64"
}

API服务器将基于容器名称自动为每个容器创建一个端点,该端点也可以通过代理进行访问。

首先,我们需要获取Pod名称,然后将其存储在环境变量POD_NAME中:

$ export POD_NAME=$(kubectl get pods -o go-template --template '\n')
dir@debian:~$ echo Name of the Pod: $POD_NAME
Name of the Pod: kubernetes-bootcamp-6f6656d949-xv7mb

为了不使用代理就可以访问新部署,需要一个服务,这将在接下来的模块中进行解释。

删除应用

$ kubectl delete deployment kubernetes-bootcamp
deployment.apps "kubernetes-bootcamp" deleted

了解应用

检查应用程序配置

使用kubectl get命令并查找现有的Pod:

pod: 紧密相关的一组容器放到一个Pod中,同一个Pod中的容器共享IP地址和Port空间。

$ kubectl get pods
NAME                                   READY   STATUS    RESTARTS   AGE
kubernetes-bootcamp-6f6656d949-xv7mb   1/1     Running   0          12m

查看该Pod中有哪些容器以及用于构建这些容器的镜像

describe命令可用于获取有关大多数kubernetes原语的详细信息:节点,pod,部署。

$ kubectl describe pods

1589943657507

获取Pod名称并将其存储在POD_NAME环境变量中

$ export POD_NAME=$(kubectl get pods -o go-template --template '\n')
$ echo Name of the Pod: $POD_NAME
Name of the Pod: kubernetes-bootcamp-6f6656d949-xv7mb

查看容器日志

使用kubectl logs命令检索容器的日志:

$ kubectl logs $POD_NAME
Kubernetes Bootcamp App Started At: 2020-05-20T02:46:53.937Z | Running On:  kubernetes-bootcamp-6f6656d949-xv7mb

在容器上执行命令

使用exec命令并将Pod的名称用作参数。 让我们列出环境变量:

$ kubectl exec $POD_NAME -- env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=kubernetes-bootcamp-6f6656d949-xv7mb
KUBERNETES_PORT=tcp://10.96.0.1:443
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
KUBERNETES_PORT_443_TCP_PROTO=tcp
KUBERNETES_PORT_443_TCP_PORT=443
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
KUBERNETES_SERVICE_HOST=10.96.0.1
KUBERNETES_SERVICE_PORT=443
KUBERNETES_SERVICE_PORT_HTTPS=443
NPM_CONFIG_LOGLEVEL=info
NODE_VERSION=6.3.1
HOME=/root

在Pod的容器中开始bash会话:

$ kubectl exec -ti $POD_NAME -- bash
root@kubernetes-bootcamp-6f6656d949-xv7mb:/# 

通过运行curl命令来检查应用程序是否启动:

root@kubernetes-bootcamp-6f6656d949-xv7mb:/# curl localhost:8080
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-6f6656d949-xv7mb | v=1

发布应用程序

创建服务

列出集群中的当前服务:

$ kubectl get services
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   15h

我们有一个名为kubernetes的服务,它是在minikube启动集群时默认创建的。

要创建新服务并将其公开给外部流量,我们将使用带有NodePort作为参数的暴露命令。

$ kubectl expose deployment/kubernetes-bootcamp --type="NodePort" --port 8080
service/kubernetes-bootcamp exposed

$ kubectl get services
NAME                  TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
kubernetes            ClusterIP   10.96.0.1       <none>        443/TCP          15h
kubernetes-bootcamp   NodePort    10.105.137.43   <none>        8080:31234/TCP   3s

为了找出外部打开了哪个端口(通过NodePort选项),我们将运行describe service命令:

$ kubectl describe services/kubernetes-bootcamp
Name:                     kubernetes-bootcamp
Namespace:                default
Labels:                   app=kubernetes-bootcamp
Annotations:              <none>
Selector:                 app=kubernetes-bootcamp
Type:                     NodePort
IP:                       10.105.137.43
Port:                     <unset>  8080/TCP
TargetPort:               8080/TCP
NodePort:                 <unset>  31234/TCP
Endpoints:                172.18.0.6:8080
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>

创建一个名为NODE_PORT的环境变量,该变量具有分配的Node端口的值:

$ export NODE_PORT=$(kubectl get services/kubernetes-bootcamp -o go-template='')
$ echo NODE_PORT=$NODE_PORT
NODE_PORT=31234

现在,我们可以使用curl,Node的IP和外部暴露的端口来测试该应用程序是否在群集外部暴露:

$ curl $(minikube ip):$NODE_PORT
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-6f6656d949-xv7mb | v=1

使用标签

部署会自动为我们的Pod创建一个标签。 使用describe deploy命令,您可以看到标签的名称:

$ kubectl describe deployment

1589945412338

使用kubectl get pods命令,并将-l作为参数,然后加上上述 Labels 值:

$ kubectl get pods -l app=kubernetes-bootcamp
NAME                                   READY   STATUS    RESTARTS   AGE
kubernetes-bootcamp-6f6656d949-xv7mb   1/1     Running   0          45m

执行相同的操作以列出现有服务:

$ kubectl get services -l app=kubernetes-bootcamp
NAME                  TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
kubernetes-bootcamp   NodePort   10.105.137.43   <none>        8080:31234/TCP   10m

获取Pod名称,然后将其存储在环境变量POD_NAME中:

$ export POD_NAME=$(kubectl get pods -o go-template --template '\n')
$ echo Name of the Pod: $POD_NAME
Name of the Pod: kubernetes-bootcamp-6f6656d949-xv7mb

要应用新标签,我们使用label命令,后跟对象类型,对象名称和新标签:

$ kubectl label pod $POD_NAME test=v1
pod/kubernetes-bootcamp-6f6656d949-xv7mb labeled

这将在我们的Pod上添加一个新标签(将应用程序版本固定到Pod),我们可以使用describe pod命令进行检查:

1589946072101

现在我们可以使用新标签查询列表:

$ kubectl get pods -l test=v1
NAME                                   READY   STATUS    RESTARTS   AGE
kubernetes-bootcamp-6f6656d949-xv7mb   1/1     Running   0          55m

删除服务

要删除服务,可以使用delete service命令。 标签也可以在这里使用:

$ kubectl delete service -l app=kubernetes-bootcamp
service "kubernetes-bootcamp" deleted

$ kubectl get services
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   15h

删除服务后,该应用程序无法从群集外部访问。

$ curl $(minikube ip):$NODE_PORT
curl: (7) Failed to connect to 172.17.0.2 port 31234: Connection refused

删除服务后,该应用程序仍在 POD 内正常运行:

$ kubectl exec -ti $POD_NAME -- curl localhost:8080
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-6f6656d949-xv7mb | v=1

扩缩应用程序

在之前的模块中,我们创建了一个 Deployment,然后通过 Service让其可以开放访问。

Deployment 仅为跑这个应用程序创建了一个 Pod。 当流量增加时,我们需要扩容应用程序满足用户需求。

扩缩 是通过改变 Deployment 中的副本数量来实现的。

扩展部署

列出部署的应用程序

$ kubectl get deployments
NAME                  READY   UP-TO-DATE   AVAILABLE   AGE
kubernetes-bootcamp   1/1     1            1           3h45m

查看部署创建的ReplicaSet

$ kubectl get rs
NAME                             DESIRED   CURRENT   READY   AGE
kubernetes-bootcamp-6f6656d949   1         1         1       3h46m

副本集的名称始终设置为 [DEPLOYMENT-NAME]-[RANDOM-STRING]

随机字符串是随机生成的,并使用 pod-template-hash 作为种子。

将Deployment扩展到4个副本。 我们将使用kubectl scale命令,然后使用部署类型,名称和所需的实例数:

$ kubectl scale deployments/kubernetes-bootcamp --replicas=4
deployment.apps/kubernetes-bootcamp scaled

检查一下Pod的数量是否已更改:

$ kubectl get deployments
NAME                  READY   UP-TO-DATE   AVAILABLE   AGE
kubernetes-bootcamp   1/4     4            4           3h49m

$ kubectl get pods
NAME                                   READY   STATUS    RESTARTS   AGE
kubernetes-bootcamp-6f6656d949-8v5jz   1/1     Running   0          3m1s
kubernetes-bootcamp-6f6656d949-hnfff   1/1     Running   0          3m1s
kubernetes-bootcamp-6f6656d949-ps58w   1/1     Running   0          3m2s
kubernetes-bootcamp-6f6656d949-xv7mb   1/1     Running   0          3h52m

现在有4个Pod,具有不同的IP地址。

1589957036478

负载均衡

检查一下服务是否在负载平衡流量。 要找出公开的IP和端口,我们可以使用describe服务:

$ kubectl describe services/kubernetes-bootcamp
Name:                     kubernetes-bootcamp
Namespace:                default
Labels:                   app=kubernetes-bootcamp
Annotations:              <none>
Selector:                 app=kubernetes-bootcamp
Type:                     NodePort
IP:                       10.105.112.40
Port:                     <unset>  8080/TCP
TargetPort:               8080/TCP
NodePort:                 <unset>  30989/TCP
Endpoints:                172.18.0.6:8080,172.18.0.7:8080,172.18.0.8:8080 + 1 more...
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>

创建一个名为NODE_PORT的环境变量,该变量的值为 NodePort

$ export NODE_PORT=$(kubectl get services/kubernetes-bootcamp -o go-template='')
dir@debian:~$ echo NODE_PORT=$NODE_PORT
NODE_PORT=30989

多次执行请求命令:

$ curl $(minikube ip):$NODE_PORT

1589957414982

会根据每个请求选择不同的Pod。 这表明负载平衡正在工作。

缩减部署

要将服务缩减到2个副本,请再次运行scale命令:

$ kubectl scale deployments/kubernetes-bootcamp --replicas=2
deployment.apps/kubernetes-bootcamp scaled

检查应用更改:

$ kubectl get deployments
NAME                  READY   UP-TO-DATE   AVAILABLE   AGE
kubernetes-bootcamp   2/2     2            2           4h5m

$ kubectl get pods
NAME                                   READY   STATUS    RESTARTS   AGE
kubernetes-bootcamp-6f6656d949-ps58w   1/1     Running   0          16m
kubernetes-bootcamp-6f6656d949-xv7mb   1/1     Running   0          4h5m

更新应用程序

用户希望应用程序始终可用,而开发人员则需要每天多次部署它们的新版本。

在 Kubernetes 中,这些是通过滚动更新(Rolling Updates)完成的。

滚动更新 允许通过使用新的实例逐步更新 Pod 实例,零停机进行 Deployment 更新。

新的 Pod 将在具有可用资源的节点上进行调度。

滚动更新允许以下操作:

升级应用程序版本

要将应用程序的映像更新到版本2,请使用set image命令,然后是部署名称和新的映像版本。

该命令通知Deployment为您的应用程序使用其他映像,并启动了滚动更新。

$ kubectl set image deployments/kubernetes-bootcamp kubernetes-bootcamp=jocatalin/kubernetes-bootcamp:v2
deployment.apps/kubernetes-bootcamp image updated

验证更新

$ curl $(minikube ip):$NODE_PORT
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-86656bc875-n2777 | v=2

也可以通过运行 rollout status 命令来确认更新:

$ kubectl rollout status deployments/kubernetes-bootcamp
deployment "kubernetes-bootcamp" successfully rolled out

查看该应用程序的当前镜像版本

$ kubectl describe pods|grep Image
    Image:          jocatalin/kubernetes-bootcamp:v2

回滚更新

执行另一个更新,然后部署标记为v10的镜像:

$ kubectl set image deployments/kubernetes-bootcamp kubernetes-bootcamp=gcr.io/google-samples/kubernetes-bootcamp:v10
deployment.apps/kubernetes-bootcamp image updated

获取部署来查看部署状态:

$ kubectl get deployments
NAME                  READY   UP-TO-DATE   AVAILABLE   AGE
kubernetes-bootcamp   3/4     2            3           4h50m

可以看到出问题了……我们没有所需数量的Pod。 再次列出Pod:

$ kubectl get pods
NAME                                   READY   STATUS             RESTARTS   AGE
kubernetes-bootcamp-64468f5bc5-9wr9q   0/1     ImagePullBackOff   0          63s
kubernetes-bootcamp-64468f5bc5-wswwl   0/1     ErrImagePull       0          64s
kubernetes-bootcamp-86656bc875-n2777   1/1     Running            0          10m
kubernetes-bootcamp-86656bc875-qc9kq   1/1     Running            0          10m
kubernetes-bootcamp-86656bc875-x6rvl   1/1     Running            0          10m

Pod上的describe命令应提供更多详情:

$ kubectl describe pods

Failed to pull image “gcr.io/google-samples/kubernetes-bootcamp:v10”: rpc error: code = Unknown desc = Error response from daemon: manifest for gcr.io/google-samples/kubernetes-bootcamp:v10 not found: manifest unknown: Failed to fetch “v10” from request “/v2/google-samples/kubernetes-bootcamp/manifests/v10”.

存储库中没有称为v10的映像。 让我们回滚到以前的工作版本。 我们将使用rollout undo命令:

$ kubectl rollout undo deployments/kubernetes-bootcamp
deployment.apps/kubernetes-bootcamp rolled back

rollout命令将部署还原到先前的已知状态(镜像的 v2 版本)。

更新是版本控制的,您可以还原到部署的任何先前已知状态。

再次列出Pod:

$ kubectl get pods
NAME                                   READY   STATUS    RESTARTS   AGE
kubernetes-bootcamp-86656bc875-n2777   1/1     Running   0          15m
kubernetes-bootcamp-86656bc875-qc9kq   1/1     Running   0          15m
kubernetes-bootcamp-86656bc875-wdkjg   1/1     Running   0          30s
kubernetes-bootcamp-86656bc875-x6rvl   1/1     Running   0          15m

再次检查部署在它们上的镜像:

$ kubectl describe pods|grep Image
    Image:          jocatalin/kubernetes-bootcamp:v2

我们看到部署正在使用该应用程序的稳定版本(v2)。 回滚成功。