Kubernetes入门

kubectl 的安装

Install and Set Up kubectl

kubernetes 含义

Kubernetes Master

Kubernetes Master 主要负责管理集群,它会协调集群内的所有活动,包括:scheduling applications, maintaining applications’ desired state, scaling applications, and rolling out new updates。
Master 实际上是三个进程的集合,它们运行在集群的一个 Master Node 上,这三个进程包括:

  • kube-apiserver:提供REST-API来操作 Kubernetes Objects,包括 pods、services、replicationcontrollers 等,并可用于控制集群状态。
  • kube-controller-manager:通过 apiserver 监听集群状态并做状态转移操作。
  • kube-scheduler:scheduler 可以根据集群的拓扑结构、性能、容量等动态分配资源。

Node

Node 是一台虚拟机或物理电脑,在集群中作为 Worker。Master 管理 Cluster,而 Node 则管理应用。
每个 Node 都有一个 Kubelet,是管理 Node 的媒介,且负责与 Kubernetes Master 进行交互。
每个 Node 还需要有工具来处理容器操作,比如 Docker 或 rkt。
一个生产环境的 cluster 必须由至少 3 个 Node 组成。

kubelet

节点代理,负责和 Kubernetes Master 交互:

  • 向 apiserver 注册节点
  • 其他云计算指定逻辑。

kube-proxy

运行于每个 Node 上的一个网络代理,可以执行简单的 TCP、UDP、SCTP 流转发或提供多后端进程的负载均衡。
相当于在主机和 Cluster 之间创建了一个连接,让我们能直接访问 API。

Pod

一个或多个应用容器集合的抽象,并且包含一些共享资源,包括:

  • 共享存储,如 Volumes;
  • 网络连接,每个 Pod 具有 Cluster 中唯一的一个 IP 地址;
  • 运行每个容器所必须的信息,比如容器镜像的版本、端口等。

Pod 建模了一种“logical host”,可以同时运行多种不同的容器。
当 Pod 所处的 Node 挂了,ReplicaSet会动态地创建新 Pod 来使得 Cluster 回到原来的状态。

Service

Service 定义了 Pod 的逻辑集合及其访问规则,虽然每个 Pod 都有一个唯一的 IP 地址(Cluster 范围内),但是如果没有 Service 的话这些 IP 也是没法暴露到 Cluster 外的,可以通过指定 ServiceSpec 中的type来指定暴露服务的方式:

  • ClusterIP (default) - Exposes the Service on an internal IP in the cluster. This type makes the Service only reachable from within the cluster.
  • NodePort - Exposes the Service on the same port of each selected Node in the cluster using NAT. Makes a Service accessible from outside the cluster using <NodeIP>:<NodePort>. Superset of ClusterIP.
  • LoadBalancer - Creates an external load balancer in the current cloud (if supported) and assigns a fixed, external IP to the Service. Superset of NodePort.
  • ExternalName - Exposes the Service using an arbitrary name (specified by externalName in the spec) by returning a CNAME record with the name. No proxy is used. This type requires v1.7 or higher of kube-dns.

Volumes

Namespaces

Deployments

负责创建和更新应用实例,创建 Deployment 后,Master 会持续监听并在各 Node 中调度应用实例,一旦有实例挂掉或被删掉,Deployment controller 就会用 Cluster 中另一 Node 上的实例取代之。

  • searched for a suitable node where an instance of the application could be run (we have only 1 available node)
  • scheduled the application to run on that Node
  • configured the cluster to reschedule the instance on a new Node when needed

DaemonSet

StatefulSets

ReplicaSet

Jobs

kubernetes 使用

可以采用kubectl命令来和 Cluster 交互,kubectl最常用的操作只有如下 4 种:

  • kubectl get - list resources
  • kubectl describe - show detailed information about a resource
  • kubectl logs - print the logs from a container in a pod
  • kubectl exec - execute a command on a container in a pod

创建Cluster

例子中使用minikube创建 Cluster,然后使用kubectl来和创建的 Cluster 交互:

1
2
3
4
5
6
7
8
9
minikube version
# 启动一个Cluster
minikube start
# 查看客户端(kubectl的版本)和服务端(Kubernetes的版本)的版本
kubectl version
# Cluster的详细信息
kubectl cluster-info
# 获取Cluster内的Node列表
kubectl get nodes
  1. 创建部署单元(Deployment)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    # 创建Deploymnet
    kubectl create deployment kubernetes-bootcamp --image=gcr.io/google-samples/kubernetes-bootcamp:v1
    # 查看Deployment
    kubectl get deployments

    # 查看Pod
    kubectl get pods
    # 查看Pod内Container的属性,比如使用的是什么镜像
    kubectl describe pods

访问

  1. 使用 proxy 访问 Service 和 Pod
    1
    2
    3
    4
    5
    6
    7
    8
    9
    # 创建proxy实例
    kubectl proxy
    # 创建proxy后可以在另一个终端调用REST API来查看Cluster信息
    curl http://localhost:8001/version
    # 查看Pod的名字
    export POD_NAME=$(kubectl get pods -o go-template --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}')
    echo Name of the Pod: $POD_NAME
    # 可以通过proxy直接访问Pod
    curl http://localhost:8001/api/v1/namespaces/default/pods/$POD_NAME/proxy/
  2. 查看日志
    1
    2
    # 所有应用发送给STDOUT的信息都会成为Pod容器的日志
    kubectl logs $POD_NAME
  3. 使用 exec 命令访问 Pod
    1
    2
    3
    4
    # 查看Pod内的环境变量
    kubectl exec $POD_NAME env
    # 在Pod中一个容器内启动一个bash会话,相当于登入了该容器
    kubectl exec -ti $POD_NAME bash

Service

  1. 创建 Service
    1
    2
    3
    4
    5
    6
    # 查看Service
    kubectl get services
    # 创建一个新的Service并暴露端口(type=NodePort可以用于占用一个Node上的端口来暴露服务)
    kubectl expose deployment/kubernetes-bootcamp --type="NodePort" --port 8080
    # 查看Service信息
    kubectl describe services/kubernetes-bootcamp
  2. Deployment 与 Service
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    # 8080其实是集群内的一个逻辑端口,可以通过以下命令获取Node上暴露的端口
    export NODE_PORT=$(kubectl get services/kubernetes-bootcamp -o go-template='{{(index .spec.ports 0).nodePort}}')
    # 然后我们可以通过curl访问Node上的端口来确认Service已经被暴露到了Cluster外
    echo NODE_PORT=$NODE_PORT

    # Deployment会自动为Pod创建一个label,可以通过如下命令来查看
    kubectl describe deployment
    # 通过label查看Pod列表和Service列表
    kubectl get pods -l run=kubernetes-bootcamp
    kubectl get services -l run=kubernetes-bootcamp
  3. Service 中的 Pod
    1
    2
    3
    4
    5
    6
    7
    8
    # 先获取Pod的名字
    export POD_NAME=$(kubectl get pods -o go-template --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}')
    echo Name of the Pod: $POD_NAME
    # 通过label命令可以设置一个新的label
    kubectl label pod $POD_NAME app=v1
    # 之后可以使用describe 命令来查看这些label,也可以使用label来查询Pod
    kubectl describe pods $POD_NAME
    kubectl get pods -l app=v1
  4. 删除 Service
    1
    2
    3
    4
    5
    6
    7
    8
    9
    # 删除一个Service
    kubectl delete service -l run=kubernetes-bootcamp
    # 查看服务列表,该服务已经被删除
    kubectl get services
    # curl端口确认不再暴露服务
    curl $(minikube ip):$NODE_PORT
    # 我们可以在Pod中运行curl来确定应用仍运行于Pod中
    kubectl exec -ti $POD_NAME curl localhost:8080
    # 如果需要终止应用,则需要同时删除Deployment

app 扩展

scaling
上图来自官网教程,Scaling 即修改 Deployment 中的 Pod 数。

  1. 扩展 ReplicaSet(Scale Up)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    # 先看下部署了几个Pod
    kubectl get deployments
    # 查看Deployment创建的ReplicaSet,ReplicaSet名的格式为[DEPLOYMENT-NAME]-[RANDOM-STRING]
    kubectl get rs
    # 将Deployment扩展为4个复制
    kubectl scale deployments/kubernetes-bootcamp --replicas=4
    # 查看Deployment及其中的Pod
    kubectl get deployments
    kubectl get pods -o wide
    # 查看Deployment的时间日志
    kubectl describe deployments/kubernetes-bootcamp
  2. Load Balancing
    1
    2
    3
    4
    5
    # 使用一个NODE_PORT环境变量来保存Node暴露的端口
    export NODE_PORT=$(kubectl get services/kubernetes-bootcamp -o go-template='{{(index .spec.ports 0).nodePort}}')
    echo NODE_PORT=$NODE_PORT
    # curl访问多次,会发现请求被负载均衡到了不同的Pod上
    curl $(minikube ip):$NODE_PORT
  3. 缩小(Scale Down)
    1
    2
    3
    4
    5
    # 再运行一次scale命令来缩小ReplicaSet
    kubectl scale deployments/kubernetes-bootcamp --replicas=2
    # 查看伸缩结果
    kubectl get deployments
    kubectl get pods -o wide

滚动更新(Rolling Update)

  1. 更新应用版本
    1
    2
    3
    4
    5
    6
    7
    8
    9
    # 先看看Cluster里有啥
    kubectl get deployments
    kubectl get pods
    # 查看应用当前使用的镜像版本
    kubectl describe pods
    # 使用set image命令设置应用的镜像版本
    kubectl set image deployments/kubernetes-bootcamp kubernetes-bootcamp=jocatalin/kubernetes-bootcamp:v2
    # 可以通过Pod查看应用的更新过程
    kubectl get pods
  2. 验证更新
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    # 确认应用正在运行中
    kubectl describe services/kubernetes-bootcamp
    # 用一个NODE_PORT环境变量保存Node暴露的端口,然后用curl确认暴露的服务可以使用
    export NODE_PORT=$(kubectl get services/kubernetes-bootcamp -o go-template='{{(index .spec.ports 0).nodePort}}')
    echo NODE_PORT=$NODE_PORT
    curl $(minikube ip):$NODE_PORT
    # 更新同样可以使用rollout status命令来确认
    kubectl rollout status deployments/kubernetes-bootcamp
    # 查看应用当前使用的镜像的版本
    kubectl describe pods
  3. 回滚(Rollback)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    # 设置镜像进行更新,但是这个镜像的v10版本是不存在的,因此会引起更新失败
    kubectl set image deployments/kubernetes-bootcamp kubernetes-bootcamp=gcr.io/google-samples/kubernetes-bootcamp:v10
    # 查看Deployment的当前状态,会发现某些Pod运行不正常
    kubectl get deployments
    # 查看Pod状态,describe能提供更多信息
    kubectl get pods
    kubectl describe pods
    # 发现问题,可以使用rollout undo命令来回滚,rollout命令会复原deployment到上一已知状态。实际上所有更新操作都是版本化的,并且每次更新都可以回滚到之前的任意版本
    kubectl rollout undo deployments/kubernetes-bootcamp
    # 接下来再查看Pod的状态可以发现所有的Pod都已经恢复运行了
    kubectl get pods
    kubectl describe pods

参考

  1. Tutorials
    Learn Kubernetes Basics
    Configuring Redis using a ConfigMap
    使用 k8s 搭建 Redis 集群
    Exposing an External IP Address to Access an Application in a Cluster
    如何使用 k8s 搭建一个无状态服务
    StatefulSet Basics
    如何使用 k8s 搭建一个有状态服务
    AppArmor
    Using Source IP
    CICD
    https://www.linux.com/tutorials/set-cicd-pipeline-jenkins-pod-kubernetes-part-2/
    https://www.linux.com/tutorials/run-and-scale-distributed-crossword-puzzle-app-cicd-kubernetes-part-3/
    https://www.linux.com/tutorials/set-cicd-distributed-crossword-puzzle-app-kubernetes-part-4/