kubernetes 入门

Kubernetes 是什么?

Kubernetes是一个可移植、可扩展的、开源的容器管理平台。简称:k8s

Kubernetes 为你提供:

  • 服务发现和负载均衡

    Kubernetes 可以使用 DNS 名称或自己的 IP 地址来曝露容器。 如果进入容器的流量很大, Kubernetes 可以负载均衡并分配网络流量,从而使部署稳定。

  • 存储编排

    Kubernetes 允许你自动挂载你选择的存储系统,例如本地存储、公共云提供商等。

  • 自动部署和回滚

    你可以使用 Kubernetes 描述已部署容器的所需状态, 它可以以受控的速率将实际状态更改为期望状态。 例如,你可以自动化 Kubernetes 来为你的部署创建新容器, 删除现有容器并将它们的所有资源用于新容器。

  • 自动完成装箱计算

    Kubernetes 允许你指定每个容器所需 CPU 和内存(RAM)。 当容器指定了资源请求时,Kubernetes 可以做出更好的决策来为容器分配资源。

  • 自我修复

    Kubernetes 将重新启动失败的容器、替换容器、杀死不响应用户定义的运行状况检查的容器, 并且在准备好服务之前不将其通告给客户端。

  • 密钥与配置管理

    Kubernetes 允许你存储和管理敏感信息,例如密码、OAuth 令牌和 ssh 密钥。 你可以在不重建容器镜像的情况下部署和更新密钥和应用程序配置,也无需在堆栈配置中暴露密钥。

容器运行时:docker、containerd、cri-o

kubernetes cluster

1656397457342.jpg

k8s 集群至少需要一个主节点(Master)和多个工作节点(Worker),主节点是集群的控制节点,负责整个集群的管理和控制,主节点主要用于暴露 API,调度部署和节点的管理。工作节点主要是运行容器的。

1656398196075.jpg

API Server 是kubernetes 中不同节点之间的主要通信节点,每个节点的多维数据集代理也负责网络通信。
Scheduler :负责计划不同节点的分配
Kube Controller Manager : 控制集群中每个节点。
Cloud Controller Manager:与云服务提供商互动(创建负载均衡器)
etcd : 存储服务,kubernetes 集群运行相关的所有日志存储在 etcd

1656397237646.jpg
1656398349483.jpg
1656406551144.jpg

kubernetes 中资源的对象

Pod

Pod 是 Kubernetes 中创建和管理的、最小的单元。容器是在pod 内部创建的。

如何创建一个Pod 资源

pod.yaml

apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  containers:
    - name: nginx
      image: nginx
      ports:
        - containerPort: 80

执行

$ kubectl apply -f pod.yaml

查看创建的资源

$ kubectl get pods
NAME    READY   STATUS    RESTARTS   AGE
nginx   1/1     Running   0          14s

资源对象的标签 label

label 是标签,k8s 中资源对象大都可以打上标签,如 Node、Pod、Service等,一个资源可以绑定任意多个 Label ,k8s 通过 Lable 可实现多维度的资源分组管理。

如何定义一个Label

apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  containers:
    - name: nginx
      image: nginx
      ports:
        - containerPort: 80

nginx 的Pod 添加了一个 Label,是app:nginx

控制器 Deployment

Deployment 管理 Replicaset 和 Pod 的副本控制器,Deployment 可以管理多个 Replicaset。
Replicaset 是k8s 中副本控制器,管理Pod,使Pod 副本的数量时装维持再预设的个数。

Deployment 是比 Replicaset 更高级的控制器,创建 Deployment 的时候,会自动创建 Replicaset ,由 Replicaset 再创建 Pod,Deployment 能对 Pod 扩容、缩容、滚动更新和回滚、维持 Pod 数量。

如何创建一个Deployment 资源

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-nginx
spec:
  selector:
    matchLabels:
      app: my-nginx
  replicas: 2
  template:
    metadata:
      labels:
        app: my-nginx
    spec:
      containers:
      - name: my-nginx
        image: nginx
        resources:
          limits:
            memory: "128Mi"
            cpu: "500m"
        ports:
        - containerPort: 80

执行

$ kubectl apply -f deployment.yaml

查看创建的 Deployment 资源

$ kubectl get deploy
NAME       READY   UP-TO-DATE   AVAILABLE   AGE
my-nginx   2/2     2            2           11s

查看创建的Replicaset 资源

$ kubectl get rs
NAME                  DESIRED   CURRENT   READY   AGE
my-nginx-7f88d7759c   2         2         2       2m36s

查看创建的 Pod 资源

$ kubectl get pods
NAME                        READY   STATUS    RESTARTS   AGE
my-nginx-7f88d7759c-pmpsf   1/1     Running   0          9s
my-nginx-7f88d7759c-sz6cl   1/1     Running   0          9s

控制器 statefulset

Deployment 控制器是用来管理无状态应用的,管理所有的 Pod,提供一个服务,也不考虑再哪台 Node 上运行,可随意扩容和缩容,这种应用称为“无状态”,例如 Web 服务,Deployment 部署的 Pod 数据卷是共享的,创建 3 个Pod 都是用的同一个数据卷,对外提供统一的服务。

在实际的场景中,尤其是分布式应用,会部署多个实例,这些实例之间有依赖关系,例如主从关系、主备关系,这种应用称为“有状态”应用,例如 MySQL 主从、Etcd 集群。

StatefulSet 控制器用于部署有状态应用,满足一些有状态场景
1、StatefulSet 管控的每个 Pod 对象都有股东的主机名和转有存储卷,即便被重构后也能保持不变。
2、Pod 有序的部署、扩容、删除和停止。
3、Pod分配一个稳定的且唯一的网络标识。
4、Pod 分配一个独享的存储。

控制器DaemonSet

DaemonSet 确保全部(或者一些)Node 上运行一个Pod 副本,当有 Node 加入集群时,也会为他们新增一个 Pod,当有 Node 从集群移除时,这些 Pod 也会被回收,删除 DaemonSet 将会删除它所创建的所有Pod。

使用 DaemonSet 的一些典型用法:
1、运行集群存储 daemon,例如在每个 Node 上运行 glusterd、ceph
2、日志收集,比如 fluentd、logstsh 等
3、系统监控,比如 Prometheus Node Exporter、collectd、New Relic agent、Ganglia gmoud 等
4、系统程序,比如 kube-proxy、kube-dns、glusterd、ceph 等

控制器 Job&CronJob

Job 负责批量处理任务,Job 创建一个或多个 Pod,并确保指定数量的 Pod 成功终止。Pod 成功终止后,Job 将跟踪成功完成的情况,当达到指定的成功完成次数是,任务(即 Job)就完成了。删除Job将清除其创建的Pod。

一个简单的情况是创建一个 Job 对象,以便可靠的运行一个 Pod 来完成,如果第一个 Pod 发生故障或被删除(例如,由于节点硬件故障或节点重启), 则 Job 对象将启动一个新的 Pod。

CronJob :一个 CronJob 对象就像 crontab 文件中的一行,它用Cron 格式进行编写,并周期性地在给定的调度时间执行 Job,在每次调度运行时间内大概会创建一个 Job 对象,我们之所以说大概,是因为再特定的环境下可能会创建两个Job ,或者一个 Job 都没创建。

service

在 kubernetes 中Pod 是有生命周期的,Pod 重启 IP 就会发生变化。如果我们的服务都是将Pod 的 IP 地址写死, Pod 的挂掉或者重启,和刚才重启的Pod 相关联的其他服务将会找不到它所关联的 Pod,为了解决这个问题,再 kubernetes 中定义了 service资源对象,service 定义了一个服务访问的入口,客户端通过这个入口即可访问服务背后的应用集群示例,service 是一组 Pod 的逻辑集合,这一组 Pod 能够被 service 访问到,通常是通过Label Selector 实现的。

如何创建一个service 资源

apiVersion: v1
kind: Service
metadata:
  name: my-nginx
  labels:
    app: my-nginx
spec:
  selector:
    app: my-nginx
  ports:
  - port: 8080
    targetPort: 80

执行

$ kubectl apply -f service.yaml

查看创建的 service 资源

$ kubectl get svc
NAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
kubernetes   ClusterIP   10.96.0.1        <none>        443/TCP    6h28m
my-nginx     ClusterIP   10.111.160.230   <none>        8080/TCP   7s

Ingress Controller

Ingress 可以把进入到集群内部的请求转发到集群中一些服务上,从而可以把服务映射到集群外部。Ingress 能把集群内 Service 配置成外网能够访问的URL ,流量负载均衡,提供基于域名访问的虚拟主机等。

Ingress Controller 可以理解为控制器,它通过不断的跟 kubernetes API 交互,实时获取后端 Service、Pod 的变化,比如新增、删除等,结合 Ingress 定义的规则生成配置,然后动态更新上边的 Nginx 或者 trafik 负载均衡器,并刷新使配置生效,来达到服务自动发现的作用,工作流程图如下:

安装minikube

安装请查看官网

https://minikube.sigs.k8s.io/docs/start/

启动minikube

win10:

minikube start --image-mirror-country=cn --driver=hyperv // 国内镜像资源启动,从阿里云镜像下载
minikube start --driver=hyperv

macos

minikube start --driver=virtualbox
// cri-o 
minikube start --driver=virtualbox --container-runtime=cri-o 
>minikube status

登录docker

>minikube ip
172.21.208.4
>ssh docker@172.21.208.4
username:docker // 默认用户和密码
password:tcuser

出现minukube 就登录了

docker ps

exit

退出docker

kubectl cluster-info
kubectl get nodes
kubectl get pods
kubectl get namespaces
kubectl get pods --namespaces=kube-system

创建nginx镜像

kubectl run nginx --image=nginx
kubectl get pods

kubectl describe pod nginx

登录docker中

docker ps | grep nginx
docker exec -it e390a73c4ef8 sh
# hostname
nginx
# hostname -i 
172.17.0.3
# curl 172.17.0.3

退出docker

kubectl get pods -o wide
kubectl delete pod nginx
kubuctl get pods
kubectl create deployment nginx-deployment --image=nginx
kubectl get deployments
kubectl get pods
kubectl describe deployment nginx-deployment
kubectl describe pod nginx-deployment-84cd76b964-tw79f

kubectl scale deployment nginx-deployment --replicas=5
kubectl get pods
kubectl get pods -o wide

登录docker中

curl 172.17.0.5

退出docker

kubectl get deployments
kubectl expose deployment nginx-deployment --port=8080 --target-port=80
kubectl get services

登录docker

curl 10.108.156.147:8080

退出 docker

kubectl describe service nginx-deployment

kubectl delete deployment nginx-deployment
kubectl delete service nginx-deployment

kubectl get deploy
// no resources found

kubectl get svc
// kubernetes

express 项目

github 地址

https://github.com/bstashchuk/k8s

上传docker

docker build wang7211401/k8s-web-hello

docker login
// 输入用户密码

docker push wang7211401/k8s-web-hello

部署

kubectl create deployment k8s-web-hello --image=wang7211401/k8s-web-hello

kubectl get pods

kubectl expose deployment k8s-web-hello --port=3000
kubectl get svc

登录docker

curl 10.97.47.157:3000

退出docker

kubectl get deploy

kubectl scale deployment k8s-web-hello --replicas=5

kubectl get pods

kubectl get pods -o wide

kubectl get svc

kubectl delete svc k8s-web-hello

端口映射

kubectl expose deployment k8s-web-hello --type=NodePort --port=3000

kubectl get svc

> minikube ip
192.168.59.101

minikube service k8s-web-hello
// 浏览器访问

> minikube service k8s-web-hello --url
http://192.168.59.101:32142

创建负载均衡器

kubectl delete svc k8s-web-hello

kubectl get svc

kubectl expose deployment k8s-web-hello --type=LoadBalancer --port=3000

kubectl get svc

minikube service k8s-web-hello

kubectl get deploy

kubectl describe deploy k8s-web-hello
// StrategyType: RollingUpdate

更新代码

express 项目

app.get("/", (req, res) => {
  const helloMessage = `VERSION 2.0.0: Hello from the ${os.hostname()}`
  console.log(helloMessage)
  res.send(helloMessage)
})

上传docker hub

docker build -t wang7211401/k8s-web-hello:2.0.0 .
docker login

docker push wang7211401/k8s-web-hello:2.0.0
kubectl set image deployment k8s-web-hello k8s-web-hello=wang7211401/k8s-web-hello:2.0.0

kubectl rollout status deploy k8s-web-hello

kubectl get pods

kubectl get svc

minikube service k8s-web-hello

回滚

kubectl set image deployment k8s-web-hello k8s-web-hello=wang7211401/k8s-web-hello

kubectl rollout status deploy k8s-web-hello

kubectl get pods

kubectl get svc

minikube service k8s-web-hello

删除其中一项pod,重新创建pod,副本数保持5项

kubectl get pods

kubectl delete pod k8s-web-hello-67bff49679-5jjxt

kubectl get pods

minikube 桌面管理界面

minikube dashboard

使用yaml

kubectl delete all -all

kubectl get pods
kubectl get svc
kubectl get deploy

deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: k8s-web-hello
spec:
  replicas: 5
  selector:
    matchLabels:
      app: k8s-web-hello
  template:
    metadata:
      labels:
        app: k8s-web-hello
    spec:
      containers:
      - name: k8s-web-hello
        image: wang7211401/k8s-web-hello
        resources:
          limits:
            memory: "128Mi"
            cpu: "250m"
        ports:
        - containerPort: 3000

启动

kubectl apply -f deployment.yaml
kubectl get deploy
kubectl get pods

service.yaml

apiVersion: v1
kind: Service
metadata:
  name: k8s-web-hello
spec:
  type: LoadBalancer
  selector:
    app: k8s-web-hello
  ports:
  - port: 3030
    targetPort: 3000

启动

kubectl apply -f service.yaml
kubectl get svc
minkube service k8s-web-hello

删除部署和服务

kubectl delete -f deployment.yaml -f service.yaml
kubectl get svc
kubectl get deploy

访问网络

index.mjs

import express from 'express'
import fetch from 'node-fetch'
import os from 'os'

const app = express()
const PORT = 3000

app.get("/", (req, res) => {
  const helloMessage = `Hello from the ${os.hostname()}`
  console.log(helloMessage)
  res.send(helloMessage)
})

app.get("/nginx", async (req, res) => {
  const url = 'http://nginx'
  const response = await fetch(url);
  const body = await response.text();
  res.send(body)
})

app.listen(PORT, () => {
  console.log(`Web server is listening at port ${PORT}`)
})

k8s-web-to-nginx.yaml

apiVersion: v1
kind: Service
metadata:
  name: k8s-web-to-nginx
spec:
  type: LoadBalancer
  selector:
    app: k8s-web-to-nginx
  ports:
  - port: 3333
    targetPort: 3000
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: k8s-web-to-nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: k8s-web-to-nginx
  template:
    metadata:
      labels:
        app: k8s-web-to-nginx
    spec:
      containers:
      - name: k8s-web-to-nginx
        image: wang7211401/k8s-web-to-nginx
        resources:
          limits:
            memory: "128Mi"
            cpu: "250m"
        ports:
        - containerPort: 3000

nginx.yaml

apiVersion: v1
kind: Service
metadata:
  name: nginx
spec:
  selector:
    app: nginx
  ports:
  - port: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  replicas: 5
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        resources:
          limits:
            memory: "128Mi"
            cpu: "125m"
        ports:
        - containerPort: 80

启动

kubectl apply -f k8s-web-to-nginx.yaml -f nginx.yaml
kubectl get deploy
kubectl get svc
kubectl get pods

minikube service k8s-web-to-nginx

解析服务的名称

kubectl exec k8s-web-to-nginx-5677575944-ftgvj -- nslookup nginx

检索路由

kubectl exec k8s-web-to-nginx-5677575944-ftgvj -- wget -q0- http://nginx

删除部署和服务

kubectl delete -f k8s-web-to-nginx.yaml -f nginx.yaml
kubectl get svc
kubectl get deploy

minikube 停止和删除

minikube stop
minikube delete

推荐阅读更多精彩内容