K8S 学习笔记二 核心技术

笔记记录尚硅谷老师的视频课
地址:https://www.bilibili.com/video/BV1GT4y1A756?p=3

2. 核心技术

2.1 命令行工具 kubectl

2.1.1 kubectl 概述

kubectl 是 Kubernetes 集群的命令行工具,通过 kubectl 能够对集群本身进行管理,并能够在集群上进行容器化应用的安装部署。

2.1.2 kubectl 命令的语法

2.1.2.1 基本格式
kubtctl [command] [TYPE] [NAME] [flags]
命令解释:
(1)comand:指定要对资源执行的操作,例如 create、get、describe 和 delete
(2)TYPE:指定资源类型,资源类型是大小写敏感的,
	开发者能够以单数、复数和缩略的形式。例如:
		kubectl get pod pod1
		kubectl get pods pod1
		kubectl get po pod1
(3)NAME:指定资源的名称,名称也大小写敏感的。
	如果省略名称,则会显示所有的资源,例如:
		kubectl get pods
(4)flags:指定可选的参数。例如,可用-s 或者–server 参数指
	定 Kubernetes APIserver 的地址和端口。
2.1.2.2 例子:
[root@k8smaster admin]# kubectl get nodes
NAME         STATUS   ROLES    AGE   VERSION
k8smaster    Ready    master   11d   v1.18.0
k8sworker1   Ready    <none>   11d   v1.18.0
k8sworker2   Ready    <none>   11d   v1.18.0
[root@k8smaster admin]# kubectl get nodes k8sworker1
NAME         STATUS   ROLES    AGE   VERSION
k8sworker1   Ready    <none>   11d   v1.18.0
2.1.2.3 kubectl --help

在这里插入图片描述

2.1.2.4 目前使用到的命令
kubectl create deployment nginx --image=nginx
kubectl expose deployment nginx --port=80 --type=NodePort
kubectl get pod,svc
kubectl get cs
kubectl get nodes
kubectl apply -f flannel.yml
2.1.2.5 子命令使用分类

(1)基础命令
在这里插入图片描述
(2)部署和集群管理命令
在这里插入图片描述
(3)故障和调试命令
在这里插入图片描述
(4)其他命令
在这里插入图片描述

2.2 资源编排 yaml

谢谢:https://blog.csdn.net/m0_54024707/article/details/122225607

2.2.1 YAML 文件概述

k8s 集群中对资源管理和资源对象编排部署都可以通过声明样式(YAML)文件来解决,也就是可以把需要对资源对象操作编辑到 YAML 格式文件中,我们把这种文件叫做资源清单文件,通过 kubectl 命令直接使用资源清单文件就可以实现对大量的资源对象进行编排部署了

2.2.2 YAML 文件书写格式

YAML 介绍

YAML :仍是一种标记语言。为了强调这种语言以数据做为中心,
		而不是以标记语言为重点。
YAML 是一个可读性高,用来表达数据序列的格式。

YAML 基本语法

* 使用空格做为缩进
* 缩进的空格数目不重要,只要相同层级的元素左侧对齐即可
* 低版本缩进时不允许使用 Tab 键,只允许使用空格
* 使用#标识注释,从这个字符一直到行尾,都会被解释器忽略

YAML 支持的数据结构

* 对象
键值对的集合,又称为映射(mapping) / 哈希(hashes) / 字典(dictionary)
如:
name: Tom
age: 18

或者
hash: {name: Tom, age: 18 }
* 数组:
一组按次序排列的值,又称为序列(sequence) / 列表 (list)
如:
People:
- Tom
- Jack

或者
People: [Tom, Jack]
纯量(scalars):
单个的、不可再分的值
如
number: 12.30
# 布尔值
isSet: true
# 日期
date: 1999-01-05
使用两个感叹号,强制转换数据类型
如:
num: !!str 123
bcd: !!str true

等等。。。----偷懒了,不记

2.2.3 YAML组成部分

2.2.3.1 控制器和被控制对象

在这里插入图片描述

2.2.3.2 部分字段说明

在这里插入图片描述
例1: apiVersion

[root@k8smaster admin]# kubectl api-versions
admissionregistration.k8s.io/v1
admissionregistration.k8s.io/v1beta1
apiextensions.k8s.io/v1
apiextensions.k8s.io/v1beta1
apiregistration.k8s.io/v1
apiregistration.k8s.io/v1beta1
apps/v1
authentication.k8s.io/v1
authentication.k8s.io/v1beta1
authorization.k8s.io/v1
authorization.k8s.io/v1beta1
autoscaling/v1
autoscaling/v2beta1
autoscaling/v2beta2
batch/v1
batch/v1beta1
certificates.k8s.io/v1beta1
coordination.k8s.io/v1
coordination.k8s.io/v1beta1
discovery.k8s.io/v1beta1
events.k8s.io/v1beta1
extensions/v1beta1
networking.k8s.io/v1
networking.k8s.io/v1beta1
node.k8s.io/v1beta1
policy/v1beta1
rbac.authorization.k8s.io/v1
rbac.authorization.k8s.io/v1beta1
scheduling.k8s.io/v1
scheduling.k8s.io/v1beta1
storage.k8s.io/v1
storage.k8s.io/v1beta1
v1

例2 kind
[root@k8smaster admin]# kubectl api-resources
在这里插入图片描述

2.2.4 快速编写YAML文件

2.2.4.1 方式一 使用 kubectl create 生成 yaml
命令:
kubectl create deployment web --image=nginx -o yaml --dry-run > m1.yaml

参数说明:
-o yaml   以yaml格式输出
deployment web   创建资源类型为deployment,名称为web的
--dry-run 空跑
> m1.yaml  内容输出到m1.yaml 中

执行结果

[root@k8smaster ~]# kubectl create deployment web --image=nginx -o yaml --dry-run > m1.yaml
W0606 23:49:11.647887   12876 helpers.go:535] --dry-run is deprecated and can be replaced with --dry-run=client.
[root@k8smaster ~]# ls
m1.yaml

[root@k8smaster ~]# cat m1.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: web
  name: web
spec:
  replicas: 1
  selector:
    matchLabels:
      app: web
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: web
    spec:
      containers:
      - image: nginx
        name: nginx
        resources: {}
status: {}

之后自己修改即可

2.2.4.2 方式二 使用 kubectl get 导出 yaml

命令:

kubectl get deploy nginx -o=yaml > m2.yaml

查看当前有哪些资源

[root@k8smaster ~]# kubectl get deploy
NAME    READY   UP-TO-DATE   AVAILABLE   AGE
nginx   1/1     1            1           12d

该资源的创建参考前面文章

https://blog.csdn.net/BogerPeng/article/details/124892243
K8S 学习笔记一 基础概念和环境搭建 -- 2.4.4.7 测试

执行结果:

[root@k8smaster ~]# kubectl get deploy nginx -o=yaml > m2.yaml
[root@k8smaster ~]# ls
m1.yaml  m2.yaml
[root@k8smaster ~]# cat m2.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  annotations:
    deployment.kubernetes.io/revision: "1"
  creationTimestamp: "2022-05-25T10:09:13Z"
  generation: 1
  labels:
    app: nginx
  managedFields:
  - apiVersion: apps/v1
    fieldsType: FieldsV1
    fieldsV1:
      f:metadata:
        f:labels:
          .: {}
          f:app: {}
      f:spec:
        f:progressDeadlineSeconds: {}
        f:replicas: {}
        f:revisionHistoryLimit: {}
        f:selector:
          f:matchLabels:
            .: {}
            f:app: {}
        f:strategy:
          f:rollingUpdate:
            .: {}
            f:maxSurge: {}
            f:maxUnavailable: {}
          f:type: {}
        f:template:
          f:metadata:
            f:labels:
              .: {}
              f:app: {}
          f:spec:
            f:containers:
              k:{"name":"nginx"}:
                .: {}
                f:image: {}
                f:imagePullPolicy: {}
                f:name: {}
                f:resources: {}
                f:terminationMessagePath: {}
                f:terminationMessagePolicy: {}
            f:dnsPolicy: {}
            f:restartPolicy: {}
            f:schedulerName: {}
            f:securityContext: {}
            f:terminationGracePeriodSeconds: {}
    manager: kubectl
    operation: Update
    time: "2022-05-25T10:09:13Z"
  - apiVersion: apps/v1
    fieldsType: FieldsV1
    fieldsV1:
      f:metadata:
        f:annotations:
          .: {}
          f:deployment.kubernetes.io/revision: {}
      f:status:
        f:availableReplicas: {}
        f:conditions:
          .: {}
          k:{"type":"Available"}:
            .: {}
            f:lastTransitionTime: {}
            f:lastUpdateTime: {}
            f:message: {}
            f:reason: {}
            f:status: {}
            f:type: {}
          k:{"type":"Progressing"}:
            .: {}
            f:lastTransitionTime: {}
            f:lastUpdateTime: {}
            f:message: {}
            f:reason: {}
            f:status: {}
            f:type: {}
        f:observedGeneration: {}
        f:readyReplicas: {}
        f:replicas: {}
        f:updatedReplicas: {}
    manager: kube-controller-manager
    operation: Update
    time: "2022-06-06T15:33:11Z"
  name: nginx
  namespace: default
  resourceVersion: "79226"
  selfLink: /apis/apps/v1/namespaces/default/deployments/nginx
  uid: e33baadd-63b5-4e42-8669-0fbd8c1aa85d
spec:
  progressDeadlineSeconds: 600
  replicas: 1
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      app: nginx
  strategy:
    rollingUpdate:
      maxSurge: 25%
      maxUnavailable: 25%
    type: RollingUpdate
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx
        imagePullPolicy: Always
        name: nginx
        resources: {}
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
      dnsPolicy: ClusterFirst
      restartPolicy: Always
      schedulerName: default-scheduler
      securityContext: {}
      terminationGracePeriodSeconds: 30
status:
  availableReplicas: 1
  conditions:
  - lastTransitionTime: "2022-05-25T10:09:13Z"
    lastUpdateTime: "2022-05-25T10:09:43Z"
    message: ReplicaSet "nginx-f89759699" has successfully progressed.
    reason: NewReplicaSetAvailable
    status: "True"
    type: Progressing
  - lastTransitionTime: "2022-06-06T15:33:11Z"
    lastUpdateTime: "2022-06-06T15:33:11Z"
    message: Deployment has minimum availability.
    reason: MinimumReplicasAvailable
    status: "True"
    type: Available
  observedGeneration: 1
  readyReplicas: 1
  replicas: 1
  updatedReplicas: 1

2.3 Pod

2.3.1 Pod 概述

Pod 是 k8s 系统中可以创建和管理的最小单元,是资源对象模型中由用户创建或部署的最小资源对象模型,也是在 k8s 上运行容器化应用的资源对象,其他的资源对象都是用来支撑或者扩展 Pod 对象功能的,比如控制器对象是用来管控 Pod 对象的,Service 或者Ingress 资源对象是用来暴露 Pod 引用对象的,PersistentVolume 资源对象是用来为 Pod提供存储等等,k8s 不会直接处理容器,而是 Pod,Pod 是由一个或多个 container 组成
Pod 是 Kubernetes 的最重要概念,每一个 Pod 都有一个特殊的被称为”根容器“的 Pause容器。Pause 容器对应的镜 像属于 Kubernetes 平台的一部分,除了 Pause 容器,每个 Pod还包含一个或多个紧密相关的用户业务容器
在这里插入图片描述

2.3.2 、Pod 特性

(1)资源共享
一个 Pod 里的多个容器可以共享存储和网络,可以看作一个逻辑的主机。共享的如
namespace,cgroups 或者其他的隔离资源。
多个容器共享同一 network namespace,由此在一个 Pod 里的多个容器共享 Pod 
的 IP 和端口 namespace,所以一个 Pod 内的多个容器之间可以通过 localhost 来进
行通信,所需要注意的是不同容器要注意不要有端口冲突即可。不同的 Pod 有不同的 IP,
不同 Pod 内的多个容器之前通信,不可以使用 IPC(如果没有特殊指定的话)通信,
通常情况下使用 Pod的 IP 进行通信。
一个 Pod 里的多个容器可以共享存储卷,这个存储卷会被定义为 Pod 的一部分,
并且可以挂载到该 Pod 里的所有容器的文件系统上。

(2)生命周期短暂
Pod 属于生命周期比较短暂的组件,比如,当 Pod 所在节点发生故障,那么该节点上
的 Pod会被调度到其他节点,但需要注意的是,被重新调度的 Pod 是一个全新的 Pod,
跟之前的Pod 没有半毛钱关系。

(3)平坦的网络
K8s 集群中的所有 Pod 都在同一个共享网络地址空间中,也就是说每个 Pod 都可以
通过其他 Pod 的 IP 

2.3.3 Pod 存在的意义

  • (1) 创建容器使用 docker, 一个docker对应的是一个容器,一个容器有进程,一个容器运行一个应用
    最佳实践是一个容器对应一个进程,但是多进程也可以运行

  • (2) Pod是多进程设计,可以同时运行多个应用程序
    Pod的存在也是为了屏蔽docker的变化 – 来自谷歌官网。即容器化不一定使用docker,其他的容器化技术也可以支持
    一个Pod可以有多个容器,一个容器里面运行一个程序

  • (3) Pod的存在是为了亲密性应用
    两个或以上的程序需要进行交互 – 如集群化的nginx
    网络之间的调用 – 如微服务程序和nginx之间的调用
    两个应用需要频繁调用 – 如微服务程序和数据库之间的调用

2.3.4 Pod的实现机制

2.3.4.1 Pod的共享网络
容器之间是相互隔离的
	通过namespace隔离进程	
	通过cgroup隔离资源
	
共享网络的前提条件:容器在同一个namespace里面

共享网络机制的实现
1. 首先创建 Pause容器(Infra容器)	
2. 其他业务容器通过Join Network Namespace 与 Infra 容器关联到一起
3. 此时它们存在于同一个namespace中,所以能实现网络的共享

相同的ip地址,和iptables规则。
2.3.4.2 Pod的共享存储

类似于docker的容器数据卷
使用数据卷进行持久化存储
在这里插入图片描述
共享存储的实现机制
在这里插入图片描述

2.3.5 镜像拉取策略

在这里插入图片描述

2.3.6 Pod 资源配置

每个 Pod 都可以对其能使用的服务器上的计算资源设置限额,Kubernetes 中可以设置
限额的计算资源有 CPU 与 Memory 两种,其中 CPU 的资源单位为 CPU 数量,是一个
绝对值而非相对值。Memory 配额也是一个绝对值,它的单 位是内存字节数。
Kubernetes 里,一个计算资源进行配额限定需要设定以下两个参数: Requests 该资
源最小申请数量,系统必须满足要求 Limits 该资源最大允许使用的量,不能突破,
当容器试图使用超过这个量的资源时,可能会被 Kubernetes
##举例
apiVersion: v1
kind: pod
metadata:
  name: frontend
spec:
  containers:
  - name: db
    image: mysql
    env: 
    - name: MYSQL_ROOT_PASSWORD
    - value: "password"
    resources:
      requests:
        memory: "64Mi"
        cpu: "250m"
      limits:
        memory: "128Mi"
        cpu: "500m" 

## 上述代码表明 MySQL 容器申请最少 0.25 个 CPU 以及 64MiB 内存,
## 在运行过程中容器所能使用的资源配额为 0.5 个 CPU 以及 128MiB 内存。
## 即调度资源和最大资源

2.3.6 Pod 重启机制

Pod 的重启策略包括 Always、OnFailure 和 Never,默认值是 Always

Always: 当容器失效时,有kubelet自动重启该容器
OnFailure: 当容器终止运行且退出码不为0时,由kubelet自动重启该容器
Never: 不论容器状态如何,kubelet都不会重启该容器

2.3.7 Pod 健康检查 – 探针

2.3.7.1 探针类型

K8s 中存在两种类型的探针:
liveness probe(存活探针)
和 readiness probee(就绪探针)
在这里插入图片描述

2.3.7.2 liveness probe(存活探针)

如果检查失败,将杀死容器,根据Pod的restartPolicy来操作

2.3.7.3 readiness probee(就绪探针)

如果检查失败,Kubenetes会把Pod从Service endpoints中移除

2.3.7.4 示例
apiVersion: v1
kind: Pod
metadata:
  name: goproxy
  labels:
    app: goproxy
spec:
  containers:
    - name: goproxy
    image: k8s.gcr.io/goproxy:0.1
    ports:
    - containerPort: 8080
    readinessProbe:
      tcpSocket:
        port: 8080
      initialDelaySeconds: 5
      periodSeconds: 10
    livenessProbe:
      tcpSocket:
        port: 8080
      initialDelaySeconds: 15
      periodSeconds: 2
2.7.3.4 每类探针都支持三种探测方法:

(1)exec:通过执行命令来检查服务是否正常,针对复杂检测或无 HTTP 接口的服务,命令返回值为 0 则表示容器健康。
(2)httpGet:通过发送 http 请求检查服务是否正常,返回 200-399 状态码则表明容器健康。
(3)tcpSocket:通过容器的 IP 和 Port 执行 TCP 检查,如果能够建立 TCP 连接,则表明容器健康。

2.3.8 Pod调度策略

2.3.8.1 创建 Pod 流程

在这里插入图片描述
Apiserver是应用接口服务,所有的组件都要经过它来读写etcd中保存的数据。
Master 节点 create pod , 通过apiserver 写入到它的存储系统etcd。
之后 Scheduler 会通过 API Server 的 watch 机制得到这个信息:有一个 Pod 需要被调度。
Node 节点,通过kubelet来读取etcd中的scheduler记录的信息,并调用docker 启动容器,并把结果返回

2.3.8.2 影响Pod调度的因素
2.3.8.2.1 Pod资源限制对Pod调度产生影响

在这里插入图片描述

2.3.8.2.2 节点选择器标签影响Pod调度
[root@k8smaster admin]# kubectl get pods -o wide
NAME                    READY   STATUS    RESTARTS   AGE   IP           NODE         NOMINATED NODE   READINESS GATES
nginx-f89759699-jqtb8   1/1     Running   3          14d   10.244.1.5   k8sworker1   <none>           <none>
[root@k8smaster admin]# kubectl label node k8sworker1 env_role=prod
node/k8sworker1 labeled
[root@k8smaster admin]# kubectl get nodes k8sworker1 --show-labels
NAME         STATUS   ROLES    AGE   VERSION   LABELS
k8sworker1   Ready    <none>   14d   v1.18.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,env_role=prod,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8sworker1,kubernetes.io/os=linux

在这里插入图片描述

2.3.8.2.3 节点亲和性影响Pod调度

节点亲和性规则:硬亲和性 required 、软亲和性 preferred。
硬亲和性规则不满足时,Pod 会置于 Pending 状态,软亲和性规则不满足时,会选择一个不匹配的节点。当节点标签改变而不再符合此节点亲和性规则时,不会将 Pod 从该节点移出,仅对新建的 Pod 对象生效

节点硬亲和性:  requiredDuringSchedulingIgnoredDuringExecution
方式一:Pod 使用 spec.nodeSelector (基于等值关系)
方式二:Pod 使用 spec.affinity 支持 matchExpressions 属性 (复杂标签选择机制

节点软亲和性:  preferredDuringSchedulingIgnoredDuringExecution
柔性控制逻辑,当条件不满足时,能接受被编排于其他不符合条件的节点之上
权重 weight 定义优先级,1-100 值越大优先级越高

Pod 反亲和调度:
Pod 反亲和调度用于分散同一类应用,调度至不同的区域、机架或节点等
将 spec.affinity.podAffinity 替换为 spec.affinity.podAntiAffinity
反亲和调度也分为柔性约束和强制约束

相关资料可以参考: https://blog.csdn.net/m0_60696725/article/details/123336069

在这里插入图片描述

2.3.8.2.4 污点和容忍度

污点 taints 是定义在节点上的键值型属性数据,用于让节点拒绝将 Pod 调度运行于其上,除非 Pod 有接纳节点污点的容忍度容忍度 tolerations 是定义在 Pod 上的键值属性数据,用于配置可容忍的污点,且调度器将 Pod 调度至其能容忍该节点污点的节点上或没有污点的节点上

污点定义于 nodes.spec.taints 容忍度定义于 pods.spec.tolerations

语法: key=value:effect

effect 定义排斥等级:
NoSchedule,不能容忍,但仅影响调度过程,已调度上去的 pod 不受影响,仅对新增加的pod 生效。
PreferNoSchedule,柔性约束,节点现存 Pod 不受影响,如果实在是没有符合的节点,也可以调度上来
NoExecute,不能容忍,当污点变动时,Pod 对象会被驱逐
# 给节点添加污点:
kubectl taint node <node-name><key>=<value>:<effect>
kubectl taint node node2 node-type=production:NoShedule #举例
# 查看节点污点:
kubectl get nodes <nodename> -o go-template={{.spec.taints}}

[root@k8smaster admin]# kubectl describe node k8smaster| grep Taint
Taints:             node-role.kubernetes.io/master:NoSchedule

# 删除节点污点:
kubectl taint node <node-name><key>[:<effect>]-
kubectl patch nodes <node-name> -p '{"spec":{"taints":[]}}'
kubectl taint node kube-node1 node-type=production:NoSchedule
kubectl get nodes kube-node1 -o go-template={{.spec.taints}}

# 删除 key 为 node-type,effect 为 NoSchedule 的污点
kubectl taint node kube-node1 node-type:NoSchedule-

# 删除 key 为 node-type 的所有污点
kubectl taint node kube-node1 node-type-

# 删除所有污点
kubectl patch nodes kube-node1 -p '{"spec":{"taints":[]}}'
2.3.8.2.5 添加删除污点案例:
###########  未加污点前,分配到的pod是随机的 (k8sworker1/k8sworker2)

[root@k8smaster admin]# kubectl create deployment web --image=nginx 
deployment.apps/web created
[root@k8smaster admin]# kubectl get pods
NAME                    READY   STATUS    RESTARTS   AGE
nginx-f89759699-qmrsd   1/1     Running   0          109s
web-5dcb957ccc-spptd    1/1     Running   0          23s
[root@k8smaster admin]# kubectl scale deployment web --replicas=5
deployment.apps/web scaled
[root@k8smaster admin]# kubectl get pods -o wide
NAME                    READY   STATUS    RESTARTS   AGE    IP           NODE         NOMINATED NODE   READINESS GATES
nginx-f89759699-qmrsd   1/1     Running   0          3m8s   10.244.2.2   k8sworker2   <none>           <none>
web-5dcb957ccc-blddj    1/1     Running   0          44s    10.244.1.9   k8sworker1   <none>           <none>
web-5dcb957ccc-d796j    1/1     Running   0          44s    10.244.2.3   k8sworker2   <none>           <none>
web-5dcb957ccc-dsgq8    1/1     Running   0          44s    10.244.1.8   k8sworker1   <none>           <none>
web-5dcb957ccc-l5t2n    1/1     Running   0          44s    10.244.2.4   k8sworker2   <none>           <none>
web-5dcb957ccc-spptd    1/1     Running   0          102s   10.244.1.7   k8sworker1   <none>           <none>
[root@k8smaster admin]# kubectl delete deployment web
deployment.apps "web" deleted
[root@k8smaster admin]# kubectl get pods -o wide
NAME                    READY   STATUS    RESTARTS   AGE   IP           NODE         NOMINATED NODE   READINESS GATES
nginx-f89759699-qmrsd   1/1     Running   0          11m   10.244.2.2   k8sworker2   <none>           <none>
############### 添加污点进k8sworker1后, 分配到的pod是k8sworker2
[root@k8smaster admin]# kubectl taint node k8sworker1 env_role=yes:NoSchedule
node/k8sworker1 tainted
[root@k8smaster admin]# kubectl describe node k8sworker1 | grep Taint
Taints:             env_role=yes:NoSchedule
[root@k8smaster admin]# kubectl create deployment web --image=nginx 
deployment.apps/web created
[root@k8smaster admin]# kubectl scale deployment web --replicas=5
deployment.apps/web scaled
[root@k8smaster admin]# kubectl get pods -o wide
NAME                    READY   STATUS              RESTARTS   AGE   IP           NODE         NOMINATED NODE   READINESS GATES
nginx-f89759699-qmrsd   1/1     Running             0          14m   10.244.2.2   k8sworker2   <none>           <none>
web-5dcb957ccc-6b857    0/1     ContainerCreating   0          15s   <none>       k8sworker2   <none>           <none>
web-5dcb957ccc-8kwkl    1/1     Running             0          60s   10.244.2.5   k8sworker2   <none>           <none>
web-5dcb957ccc-bkq48    0/1     ContainerCreating   0          15s   <none>       k8sworker2   <none>           <none>
web-5dcb957ccc-vxrxx    1/1     Running             0          15s   10.244.2.6   k8sworker2   <none>           <none>
web-5dcb957ccc-zhmxx    0/1     ContainerCreating   0          15s   <none>       k8sworker2   <none>           <none>
##################  删除污点
[root@k8smaster admin]# kubectl describe node k8sworker1 | grep Taint
Taints:             env_role=yes:NoSchedule
[root@k8smaster admin]# kubectl taint node k8sworker1 env_role=yes:NoSchedule-
node/k8sworker1 untainted
[root@k8smaster admin]# kubectl describe node k8sworker1 | grep Taint
Taints:             <none>

2.4 Controller 控制器 deployment

2.4.1 Controller 介绍

在集群上管理和运行容器的对象

2.4.2 Pod和Controller关系

Pod是通过Controller实现应用的运维,比如伸缩,滚动升级等
Pod和Controller之间通过 selector 和 label 标签建立关系
在这里插入图片描述

2.4.3 Deployment Controller应用场景说明

部署无状态应用
管理Pod和ReplicaSet(副本)
部署,滚动升级等功能
应用场景:web服务,微服务

2.4.4 yaml资源编排

在这里插入图片描述

#### 生成 yaml 文件, 可以参考 2.2 节

[root@k8smaster ~]# kubectl create deployment web --image=nginx --dry-run -o yaml > web.yaml
W0610 01:23:32.920650   28489 helpers.go:535] --dry-run is deprecated and can be replaced with --dry-run=client.

[root@k8smaster ~]# cat web.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: web
  name: web
spec:
  replicas: 2
  selector:
    matchLabels:
      app: web
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: web
    spec:
      containers:
      - image: nginx
        name: nginx
        resources: {}
status: {}

2.4.5 Deployment Controller部署应用

2.4.5.1 生成yaml文件

参考 2.4.4

2.4.5.2 使用 yaml 文件进行应用部署
[root@k8smaster ~]# kubectl apply -f web.yaml 
deployment.apps/web created

##### 查看状态
[root@k8smaster ~]# kubectl get pods
NAME                    READY   STATUS              RESTARTS   AGE
nginx-f89759699-qmrsd   1/1     Running             0          107m
web-5dcb957ccc-l7hdx    0/1     Running                0          9s

2.4.5.3 对外暴露端口号
## 生成 yaml 文件
[root@k8smaster ~]# kubectl expose deployment web --port=80 --type=NodePort --target-port=80 --name=web2 -o yaml > web2.yaml

[root@k8smaster ~]# cat web2.yaml 
apiVersion: v1
kind: Service
metadata:
  creationTimestamp: "2022-06-09T17:25:03Z"
  labels:
    app: web
  managedFields:
  - apiVersion: v1
    fieldsType: FieldsV1
    fieldsV1:
      f:metadata:
        f:labels:
          .: {}
          f:app: {}
      f:spec:
        f:externalTrafficPolicy: {}
        f:ports:
          .: {}
          k:{"port":80,"protocol":"TCP"}:
            .: {}
            f:port: {}
            f:protocol: {}
            f:targetPort: {}
        f:selector:
          .: {}
          f:app: {}
        f:sessionAffinity: {}
        f:type: {}
    manager: kubectl
    operation: Update
    time: "2022-06-09T17:25:03Z"
  name: web2
  namespace: default
  resourceVersion: "111085"
  selfLink: /api/v1/namespaces/default/services/web2
  uid: aa69a1da-43d9-48b8-a72e-4da96b480450
spec:
  clusterIP: 10.109.82.132
  externalTrafficPolicy: Cluster
  ports:
  - nodePort: 31768
    port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: web
  sessionAffinity: None
  type: NodePort
status:
  loadBalancer: {}

### 再次进行应用部署
[root@k8smaster ~]# kubectl apply -f web2.yaml 
Warning: kubectl apply should be used on resource created by either kubectl create --save-config or kubectl apply
service/web2 configured

[root@k8smaster ~]# kubectl get pod,svc
NAME                        READY   STATUS    RESTARTS   AGE
pod/nginx-f89759699-qmrsd   1/1     Running   0          110m
pod/web-5dcb957ccc-l7hdx    1/1     Running   0          3m26s

NAME                 TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
service/kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP        15d
service/web2         NodePort    10.109.82.132   <none>        80:31768/TCP   2m48s

验证:两台 workernode都能够登录nginx
在这里插入图片描述

2.4.5.4 删除 deployment 的内容
## 查看pods,  svc,  deployment
[root@k8smaster admin]# kubectl get pods
NAME                    READY   STATUS    RESTARTS   AGE
web-5dcb957ccc-l7hdx    1/1     Running   1          22h
[root@k8smaster admin]# kubectl get svc
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
web2         NodePort    10.109.82.132   <none>        80:31768/TCP   22h
[root@k8smaster admin]# kubectl get deployment
NAME    READY   UP-TO-DATE   AVAILABLE   AGE
web     1/1     1            1           22h

## 删除 deployment 和 svc 后, pod也会自动关闭
[root@k8smaster admin]# kubectl delete deployment web
deployment.apps "web" deleted
[root@k8smaster admin]# kubectl delete svc web2
service "web2" deleted

[root@k8smaster admin]# kubectl get pods
NAME                    READY   STATUS    RESTARTS   AGE

2.4.6 deployment 的升级回滚

2.4.6.1 升级
  • (1). 修改 "2.4.4 yaml资源编排"中生成的web.yaml文件
    在这里插入图片描述
把 image: nginx  修改为  image: nginx:1.14, 也即是添加版本号
把 replicas 数量设置为2,即两个副本
  • (2). 使用 kubectl apply -f web.yaml 部署
[root@k8smaster ~]# kubectl apply -f web.yaml 
deployment.apps/web created
## 有两个pod
[root@k8smaster ~]# kubectl get pods
NAME                    READY   STATUS    RESTARTS   AGE
web-65b7447c7-7jrwv     1/1     Running   0          95s
web-65b7447c7-vgnk7     1/1     Running   0          95s
## 有两个副本
[root@k8smaster ~]# kubectl get deployment
NAME    READY   UP-TO-DATE   AVAILABLE   AGE
web     2/2     2            2           116s

此时在两台worker机器上,能看到nginx的版本有个1.14

[root@k8sworker1 admin]# docker images
REPOSITORY                                           TAG                 IMAGE ID            CREATED             SIZE
rancher/mirrored-flannelcni-flannel                  v0.17.0             9247abf08677        3 months ago        59.8MB
rancher/mirrored-flannelcni-flannel-cni-plugin       v1.0.1              ac40ce625740        4 months ago        8.1MB
nginx                                                latest              605c77e624dd        5 months ago        141MB
registry.aliyuncs.com/google_containers/kube-proxy   v1.18.0             43940c34f24f        2 years ago         117MB
registry.aliyuncs.com/google_containers/pause        3.2                 80d28bedfe5d        2 years ago         683kB
nginx                                                1.14                295c7be07902        3 years ago         109MB
  • (3). nginx升级成1.15
## 执行脚本,并等待升级
[root@k8smaster ~]# kubectl set image deployment web nginx=nginx:1.15
deployment.apps/web image updated

此时worker机器存在 1.15 版本的nginx

[root@k8sworker1 admin]# docker images
REPOSITORY                                           TAG                 IMAGE ID            CREATED             SIZE
rancher/mirrored-flannelcni-flannel                  v0.17.0             9247abf08677        3 months ago        59.8MB
rancher/mirrored-flannelcni-flannel-cni-plugin       v1.0.1              ac40ce625740        4 months ago        8.1MB
nginx                                                latest              605c77e624dd        5 months ago        141MB
registry.aliyuncs.com/google_containers/kube-proxy   v1.18.0             43940c34f24f        2 years ago         117MB
registry.aliyuncs.com/google_containers/pause        3.2                 80d28bedfe5d        2 years ago         683kB
nginx                                                1.15                53f3fd8007f7        3 years ago         109MB
nginx                                                1.14                295c7be07902        3 years ago         109MB

升级过程:会先拉取镜像,然后生成pods,新版本的运行起来后,才会删掉旧版本的服务,保证升级过程中服务不中断

## 升级中
[root@k8smaster ~]# kubectl get pods
NAME                    READY   STATUS              RESTARTS   AGE
web-65b7447c7-7jrwv     0/1     Terminating         0          10m
web-65b7447c7-vgnk7     1/1     Running             0          10m
web-7d9697b7f8-645g7    0/1     ContainerCreating   0          10s
web-7d9697b7f8-f56ln    1/1     Running             0          38s
## 升级后
[root@k8smaster ~]# kubectl get pods
NAME                    READY   STATUS    RESTARTS   AGE
web-7d9697b7f8-645g7    1/1     Running   0          3m44s
web-7d9697b7f8-f56ln    1/1     Running   0          4m12s
  • (4). 查看升级状态

命令: kubectl rollout status deployment web

[root@k8smaster ~]# kubectl rollout status deployment web
deployment "web" successfully rolled out
2.4.6.2 回滚
  • (1). 查看升级版本:
    命令:kubectl rollout history deployment web
[root@k8smaster ~]# kubectl rollout history deployment web
deployment.apps/web 
REVISION  CHANGE-CAUSE
1         <none>
2         <none>
  • (2). 回滚到上一个版本:
    命令: kubectl rollout undo deployment web
[root@k8smaster ~]# kubectl rollout undo deployment web
deployment.apps/web rolled back
[root@k8smaster ~]# kubectl rollout status deployment web
deployment "web" successfully rolled out
  • (3). 回滚到指定版本
    命令: kubectl rollout undo deployment web --to-revision=2
[root@k8smaster ~]# kubectl rollout undo deployment web --to-revision=2
deployment.apps/web rolled back
[root@k8smaster ~]# kubectl rollout status deployment web
deployment "web" successfully rolled out
[root@k8smaster ~]# kubectl rollout history deployment web
deployment.apps/web 
REVISION  CHANGE-CAUSE
3         <none>
4         <none>

2.4.7 deployment 的弹性伸缩 scale

命令:kubectl scale deployment web --replicas=6

### 增加副本前
[root@k8smaster ~]# kubectl get pods
NAME                    READY   STATUS    RESTARTS   AGE
web-7d9697b7f8-5q42w    1/1     Running   0          112s
web-7d9697b7f8-mbmx5    1/1     Running   0          111s
[root@k8smaster ~]# kubectl scale deployment web --replicas=6
deployment.apps/web scaled

### 增加副本后
[root@k8smaster ~]# kubectl get pods
NAME                    READY   STATUS    RESTARTS   AGE
web-7d9697b7f8-5q42w    1/1     Running   0          3m23s
web-7d9697b7f8-6l4fh    1/1     Running   0          3s
web-7d9697b7f8-8pk8l    1/1     Running   0          3s
web-7d9697b7f8-8z6mv    1/1     Running   0          3s
web-7d9697b7f8-ltkh4    1/1     Running   0          3s
web-7d9697b7f8-mbmx5    1/1     Running   0          3m22s

2.5 Service 服务发现

2.5.1 Service存在意义

  • (1). 防止 Pod 失联
    Pod是短暂的,每次操作后,IP地址都可能更新。每次Pod的IP发生更新的时候,会重新注册到service,service再通知其他服务
    在这里插入图片描述
  • (2). 定义一组关于Pod的访问策略(负载均衡)
    在这里插入图片描述

2.5.2 Service与Pod的关系

Service 也有IP, 虚拟IP(VIP)
在这里插入图片描述

2.5.3 常见service类型

kubectl expose --help

--type='': Type for this service: ClusterIP, NodePort, LoadBalancer, or ExternalName. Default is 'ClusterIP'.
  • (1). ClusterIP: 集群内部时使用
  • (2). NodePort: 对外访问应用
  • (3). LoadBalancer: 对外访问应用, 公有云

三个service类型的例子

2.5.3.1 ClusterIP

例子:参考 2.4.5.3 web.yaml

### 默认是NodePort,那么可以在两个 workerNode上访问到,如2.4.5.3的例子
[root@k8smaster ~]# kubectl create deployment web --image=nginx --dry-run -o yaml > web.yaml
W0610 01:23:32.920650   28489 helpers.go:535] --dry-run is deprecated and can be replaced with --dry-run=client.

[root@k8smaster ~]# kubectl apply -f web.yaml 
deployment.apps/web created

[root@k8smaster ~]# kubectl expose deployment web --port=80 --target-port=80 --dry-run -o yaml > service1.yaml

### 此时默认的 type为ClusterIP, 类似下面图片
[root@k8smaster ~]# cat service1.yaml 
apiVersion: v1
kind: Service
metadata:
  creationTimestamp: null
  labels:
    app: web
  name: web
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: web
status:
  loadBalancer: {}

在这里插入图片描述

### 看效果, type是ClusterIP
[root@k8smaster ~]# kubectl get svc
NAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1        <none>        443/TCP   17d
web          ClusterIP   10.109.239.241   <none>        80/TCP    6s
### curl 访问该deployment的IP
[root@k8smaster ~]# curl 10.109.239.241
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
2.5.3.2 NodePort
## 修改 2.5.3.1 的service1.yaml, 
## 修改name: web1  ,  添加 type: NodePort  如下
[root@k8smaster ~]# cat service1.yaml 
apiVersion: v1
kind: Service
metadata:
  creationTimestamp: null
  labels:
    app: web
  name: web
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: web
  type: NodePort
status:
  loadBalancer: {}

执行脚本及结果:

[root@k8smaster ~]# kubectl apply -f service1.yaml 
service/web1 created
[root@k8smaster ~]# kubectl get svc
NAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
kubernetes   ClusterIP   10.96.0.1        <none>        443/TCP        17d
web          ClusterIP   10.109.239.241   <none>        80/TCP         10m
web1         NodePort    10.96.98.50      <none>        80:32513/TCP   6s

注意,上方的web1为 NodePort,那么在任意的workernode,可以通过32513的端口访问到nginx

2.5.3.2 LoadBalancer
node内网部署应用,外网一般不能访问到
如果自己搭负载均衡,一般执行的方式:
* 找到一台可以进行外网访问的机器,安装nginx,反向代理
* 手动把可以访问的节点添加到nginx里面

公有云的LoadBalancer能帮我们做到上述的执行方式,而不必自己配置

2.6 Controller (StatefulSet) 部署有状态应用

2.6.1 有状态和无状态应用的区别

无状态:
	* 认为 Pod 都是一样的
	*  没有顺序要求
	*  不用考虑在哪个node上运行
	*  可随意进行伸缩扩展
有状态:
	* 上面因素都需要考虑到
	*  它让每个Pod都是独立的,保持Pod的启动顺序和唯一性
		    使用唯一的网络标识符来区分
		    有序,比如mysql主从

2.6.2 部署有状态应用

2.6.2.1 无头service

部署的应用的 ClusterIP: none 的应用

2.6.2.2 StatefulSet 部署

参照web.yaml编写出sts.yaml,内容如下
clusterIP: None ---- 必需
kind: StatefulSet ---- 必需

apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  ports:
  - port: 80
    name: web
  clusterIP: None
  selector:
    app: nginx
    
---

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: nginx-statefulset
  namespace: default
spec:
  serviceName: nginx
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 80

执行结果:

[root@k8smaster ~]# kubectl apply -f sts.yaml 
service/nginx created
statefulset.apps/nginx-statefulset created

## 查看Pod
### Pod 中nginx-statefulset 有序号 -0 -1 -2
[root@k8smaster ~]# kubectl get pods
NAME                    READY   STATUS    RESTARTS   AGE
nginx-f89759699-qmrsd   1/1     Running   3          3d1h
nginx-statefulset-0     1/1     Running   0          54s
nginx-statefulset-1     1/1     Running   0          36s
nginx-statefulset-2     1/1     Running   0          19s
web-65b7447c7-m9pnc     1/1     Running   1          24h
web-65b7447c7-qr2gq     1/1     Running   1          24h

## 查看service(svc), CLUSTER-IP 是 None
[root@k8smaster ~]# kubectl get svc
NAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
kubernetes   ClusterIP   10.96.0.1        <none>        443/TCP        18d
nginx        ClusterIP   None             <none>        80/TCP         2m2s
web          ClusterIP   10.109.239.241   <none>        80/TCP         24h
web1         NodePort    10.96.98.50      <none>        80:32513/TCP   24h

2.6.3 StatefulSet和deployment的区别

StatefulSet 是有身份的(唯一标识的)
它会根据主机名 + 按照一定规则生成域名
应用场景就如前面说到的mysql主从部署

## 特点:
每个Pod有唯一主机名
唯一域名
## 生成格式:
主机名称.service名称.名称空间.svc.cluster.local
如: nginx-statefulset-0.nginx.default.svc.cluster.local

2.7 Controller(DaemonSet)部署守护进程

每个node上运行一个pod,新加入的node也同样给他们新增一个pod
参考这里: https://blog.csdn.net/wc1695040842/article/details/106356854

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

例子:在每个node节点安装数据采集工具
新建ds.yaml

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: ds-test
  labels:
    app: filebeat
spec:
  selector:
    matchLabels:
      app: filebeat
  template:
    metadata:
      labels:
        app: filebeat
    spec:
      containers:
      - name: logs
        image: nginx
        ports:
        - containerPort: 80
        volumeMounts:
        - name: varlog
          mountPath: /temp/log
      volumes:
      - name: varlog
        hostPath:
          path: /var/log
[root@k8smaster ~]# kubectl apply -f ds.yaml 
daemonset.apps/ds-test created

[root@k8smaster ~]# kubectl get pods
NAME                    READY   STATUS    RESTARTS   AGE
ds-test-pgxhs           1/1     Running   0          70s
ds-test-zl4lv           1/1     Running   0          70s
nginx-f89759699-qmrsd   1/1     Running   4          4d

root@ds-test-pgxhs:/temp/log# cd /temp/log
root@ds-test-pgxhs:/temp/log# ls
Xorg.0.log	boot.log-20220525  dmesg	       lastlog	 ppp	  speech-dispatcher	vmware-network.2.log  vmware-network.8.log	wpa_supplicant.log
Xorg.0.log.old	btmp		   dmesg.old	       libvirt	 qemu-ga  spooler		vmware-network.3.log  vmware-network.9.log	wtmp
Xorg.9.log	chrony		   firewalld	       maillog	 rhsm	  swtpm			vmware-network.4.log  vmware-network.log	yum.log
anaconda	containers	   gdm		       messages  sa	  tallylog		vmware-network.5.log  vmware-vgauthsvc.log.0
audit		cron		   glusterfs	       pluto	 samba	  tuned			vmware-network.6.log  vmware-vmsvc-root.log
boot.log	cups		   grubby_prune_debug  pods	 secure   vmware-network.1.log	vmware-network.7.log  vmware-vmtoolsd-root.log

结果即是,当设置kind: DaemonSet 的时候,尽管ds.yaml中没有指定副本数量,但是每个node都会运行起一个pod

2.8 Controller Job和CronJob

2.8.1 一次性任务(Job)

编写一个文件 job.yaml
把pi 打印到小数点后2000位

apiVersion: batch/v1
kind: Job
metadata:
  name: pi
spec:
  template:
    spec:
      containers:
      - name: pi
        image: perl
        command: ["perl", "-Mbignum=bpi","-wle","print bpi(2000)"]
      restartPolicy: Never
  backoffLimit: 4
[root@k8smaster ~]# kubectl apply -f job.yaml 
job.batch/pi created

## pod创建中
[root@k8smaster ~]# kubectl get pods
NAME                    READY   STATUS              RESTARTS   AGE
nginx-f89759699-qmrsd   1/1     Running             4          4d
pi-nzwqw                0/1     ContainerCreating   0          9s
## 运行完毕pod关闭
[root@k8smaster ~]# kubectl get pods
NAME                    READY   STATUS      RESTARTS   AGE
nginx-f89759699-qmrsd   1/1     Running     4          4d
pi-nzwqw                0/1     Completed   0          55s

查看日志:kubectl logs pi-nzwqw
在这里插入图片描述
此时删除一次性任务

[root@k8smaster ~]# kubectl delete -f job.yaml 
job.batch "pi" deleted
[root@k8smaster ~]# kubectl get jobs
No resources found in default namespace.

2.8.2 定时任务(CronJob)

详细也可以参考另外一篇文章: https://blog.51cto.com/breaklinux/2445802?source=dra

例子:每隔一段时间输出一个字段
新建文件 cronjob.yaml

apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: hello
spec:
  schedule: "*/1 * * * *"
  jobTemplate:
    spec:
      template:
        spec: 
          containers:
          - name: hello
            image: busybox
            args:
            - /bin/sh
            - -c
            - date; echo Hello from the K8S cluster
          restartPolicy: OnFailure

执行命令

[root@k8smaster ~]# kubectl apply -f cronjob.yaml 
cronjob.batch/hellp created

结果:每隔60秒钟就创建一个hello的pod,完成后显示Completed

[root@k8smaster ~]# kubectl get pods
NAME                     READY   STATUS      RESTARTS   AGE
hello-1655138760-7h6kr   0/1     Completed   0          116s
hello-1655138820-wmf26   0/1     Completed   0          56s
nginx-f89759699-qmrsd    1/1     Running     4          4d1h
[root@k8smaster ~]# kubectl logs hello-1655138760-7h6kr
Mon Jun 13 16:46:23 UTC 2022
Hello from the K8S cluster

查看:kubectl get cronjobs / kubectl get cronjob hello

[root@k8smaster ~]# kubectl get cronjobs
NAME    SCHEDULE      SUSPEND   ACTIVE   LAST SCHEDULE   AGE
hello   */1 * * * *   False     0        44s             87s

删除:

[root@k8smaster ~]# kubectl delete cronjob hello
cronjob.batch "hello" deleted

2.9 配置管理 secret

2.9.1 作用

加密数据并存在 etcd 里面,让Pod容器以挂载Volume方式进行访问
Secret 存在意义
Secret 解决了密码、token、密钥等敏感数据的配置问题,而不需要把这些敏感数据暴露到镜像或者 Pod Spec 中。Secret 可以以 Volume 或者环境变量的方式使用

2.9.2 场景

如设置凭证

base64编码:

## 把admin用base64编码
[admin@k8smaster ~]$ echo -n 'admin' | base64
YWRtaW4=
[admin@k8smaster ~]$ echo -n 'admin123' | base64
YWRtaW4xMjM=

2.9.3 实例

2.9.3.1 创建 secret 加密数据

新建 secret.yaml 文件

apiVersion: v1
kind: Secret
metadata:
  name: mysecret
type: Opaque
data:
  username: YWRtaW4=
  password: YWRtaW4xMjM=

创建 secret

[root@k8smaster ~]# kubectl create -f secret.yaml 
secret/mysecret created
[root@k8smaster ~]# kubectl get secret
NAME                  TYPE                                  DATA   AGE
default-token-s9rrz   kubernetes.io/service-account-token   3      20d
mysecret              Opaque       
2.9.3.2 以变量的形式挂载到Pod容器中

创建文件 secret-var.yaml
操作:nginx登录的时候,需要使用账号密码,而账号和密码是从名称为mysecret的secret中获取的

apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
    - name: nginx
      image: nginx 
      env:
      - name: SECRET_USERNAME
        valueFrom:
          secretKeyRef:
            name: mysecret
            key: username
      - name: SECRET_PASSWORD
        valueFrom:
          secretKeyRef:
            name: mysecret
            key: password

执行结果:

[root@k8smaster ~]# kubectl apply -f secret-var.yaml 
pod/mypod created
NAME                    READY   STATUS    RESTARTS   AGE
mypod                   1/1     Running   0          43s
nginx-f89759699-qmrsd   1/1     Running   5          5d

验证密码:

[root@k8smaster ~]# kubectl exec -it mypod bash
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl kubectl exec [POD] -- [COMMAND] instead.
root@mypod:/# echo $SECRET_USERNAME
admin
root@mypod:/# echo $SECRET_PASSWORD
admin123
2.9.3.3 以Volume的形式挂载到Pod容器中

新建文件secret-val.yaml

apiVersion: v1
kind: Pod
metadata:
  name: mypod2
spec:
  containers:
    - name: nginx
      image: nginx 
      volumeMounts:
      - name: foo
        mountPath: "/etc/foo"
        readOnly: true
  volumes:
  - name: foo
    secret: 
      secretName: mysecret

执行命令查看结果:

[root@k8smaster ~]# kubectl apply -f secret-val.yaml 
pod/mypod2 created
[root@k8smaster ~]# kubectl get pods
NAME                    READY   STATUS    RESTARTS   AGE
mypod                   1/1     Running   0          15m
mypod2                  1/1     Running   0          5s
nginx-f89759699-qmrsd   1/1     Running   5          5d1h

## 进入mypod2中,能看到 /etc/foo 下面有password和username
[root@k8smaster ~]# kubectl exec -it mypod2 bash
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl kubectl exec [POD] -- [COMMAND] instead.
root@mypod2:/# cd /etc/foo
root@mypod2:/etc/foo# ls
password  username

应用场景:可以将 jdbc的参数写到文件进行引用

2.10 配置管理 ConfigMap

2.10.1 什么是ConfigMap

与Secret相似,但是存储的是不加密的数据,让Pod以变量或者Volume挂载到容器中。
一般用于放置服务的配置文件

2.10.2 配置实例

自己参考另外文件:https://blog.csdn.net/skh2015java/article/details/109228836
https://www.jianshu.com/p/b1d516f02ecd

2.10.1.1 创建配置文件myredis.properties
redis.host=127.0.0.1
redis.port=6379
redis.password=123456
2.10.1.2 创建ConfigMap
## 创建 myredis-config 
[root@k8smaster ~]# kubectl create configmap myredis-config --from-file=myredis.properties
configmap/myredis-config created
[root@k8smaster ~]# kubectl get cm
NAME             DATA   AGE
myredis-config   1      10s

## 查看
[root@k8smaster ~]# kubectl describe cm myredis-config
Name:         myredis-config
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
myredis.properties:
----
redis.host=127.0.0.1
redis.port=6379
redis.password=123456

Events:  <none>
2.10.1.3 以volume挂载到pod中

创建文件 cm.yaml

apiVersion: v1
kind: Pod
metadata:
  name: mypod3
spec:
  containers:
    - name: busybox
      image: busybox
      securityContext:
        privileged: true
      command: [ "/bin/sh","-c","cat /etc/config/myredis.properties"]
      volumeMounts:
      - name: config-volume
        mountPath: /etc/config
  volumes:
  - name: config-volume
    configMap: 
      name: myredis-config
  restartPolicy: Never

执行并查看结果,状态是Completed,
并且日志把内容打印出来了

[root@k8smaster ~]# kubectl apply -f cm.yaml 
pod/mypod3 created

[root@k8smaster ~]# kubectl get pods
NAME                    READY   STATUS      RESTARTS   AGE
ds-test-pgxhs           1/1     Running     2          4d
ds-test-zl4lv           1/1     Running     2          4d
mypod3                  0/1     Completed   0          87s
nginx-f89759699-qmrsd   1/1     Running     6          8d

## 把结果打印出来了
[root@k8smaster ~]# kubectl logs mypod3
redis.host=127.0.0.1
redis.port=6379
redis.password=123456

2.10.1.4 以变量挂载到pod中

新建文件 configmap.yaml

apiVersion: v1
kind: ConfigMap
metadata:
  name: myconfig
  namespace: default
data:
  special.level: info
  special.type: hello

执行configmap.yaml

[root@k8smaster ~]# kubectl apply -f configmap.yaml 
configmap/myconfig created
[root@k8smaster ~]# kubectl get cm
NAME             DATA   AGE
myconfig         2      8s
myredis-config   1      66m

执行config-var.yaml 并查看挂载结果结果:

[root@k8smaster ~]# kubectl apply -f config-var.yaml 
pod/mypod4 created
[root@k8smaster ~]# kubectl get pods
NAME                    READY   STATUS      RESTARTS   AGE
mypod4                  0/1     Completed   0          10s
nginx-f89759699-qmrsd   1/1     Running     6          8d
[root@k8smaster ~]# kubectl logs mypod4
info hello

2.11 集群安全机制

2.11.1 概述

访问k8s集群时候,需要经过三个步骤才能进行具体操作

第一 认证
第二 授权(鉴权)
第三 准入控制
进行访问的时候,过程中都需要经过apiserver(作统一协调管理)
apiserver作统一协调,类似门卫的功能。
在访问过程中需要证书、token、或者用户名+密码才能访问
如果访问pod,需要serviceAccount

在这里插入图片描述

2.11.1.1 认证

传输安全:
对外不暴露8080端口,只能内部访问,对外使用6443端口

客户端认证常用方式:

https证书认证,基于ca证书
http token认证,通过token识别用户
http基本认证, 用户名+密码 认证
2.11.1.2 授权

基于RBAC(基于角色的访问控制)进行鉴权

2.11.1.3 准入控制

就是持有一个准入控制器的列表,如果列表有请求内容则通过,没有则拒绝

2.11.2 RBAC 介绍

RBAC 基于角色的访问控制:

角色: 
每个角色都有特定的权限,当某个账号被赋予某个角色时(角色绑定到账号),
这个账号就拥有该角色的所有功能

role: 特定命名空间的访问权限
CLusterRole: 所有命名空间访问权限

角色绑定
roleBinding: 角色绑定到主体
ClusterRoleBinding: 集群角色绑定到主题

主体:
user:用户
group: 用户组
serviceAccount: 服务账号

在这里插入图片描述

2.11.3 RBAC 实现鉴权

备注:这个是在二进制安装的环境下演示的,如果是在kubeadm安装的环境,得重新把
https://blog.csdn.net/BogerPeng/article/details/124892243
“2.5.6.1 生成 kube-apiserver 证书” 先走完一遍,打通apiserver

2.11.3.1 创建命名空间和pod
##### 创建命名空间
[root@k8smaster admin]# kubectl create ns roledemo
namespace/roledemo created

##### 在新创建的命名空间下创建pod
[root@k8smaster admin]# kubectl run nginx --image=nginx -n roledemo
pod/nginx created
[root@k8smaster admin]# kubectl get pods -n roledemo
NAME    READY   STATUS    RESTARTS   AGE
nginx   1/1     Running   0          34s

2.11.3.2 创建角色

创建执行 rbac-role.yaml, 角色拥有get/watch/list的权限

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: pod-reader
  namespace: roledemo
rules:
- apiGroups: [""]  # "" indicates the core API group
  resources: ["pods"]
  verbs: ["get","watch","list"]

执行rbac-role.yaml 创建角色

[root@k8smaster ~]# kubectl apply -f rbac-role.yaml 
role.rbac.authorization.k8s.io/pod-reader created
[root@k8smaster ~]# kubectl get role -n roledemo
NAME         CREATED AT
pod-reader   2022-06-18T02:11:04Z
2.11.3.3 创建角色绑定

新建rbac-rolebinding.yaml 脚本,账号zhangsan

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: read-pods
  namespace: roledemo
subjects:
- kind: User
  name: zhangsan # Name is case sensitive
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role # this must be Role or ClusterRole
  name: pod-reader # this must match the name of the Role or ClusterRole you wish to bind to
  apiGroup: rbac.authorization.k8s.io

绑定角色到账户

[root@k8smaster ~]# kubectl apply -f rbac-rolebinding.yaml 
rolebinding.rbac.authorization.k8s.io/read-pods created
[root@k8smaster ~]# kubectl get role,rolebinding -n roledemo
NAME                                        CREATED AT
role.rbac.authorization.k8s.io/pod-reader   2022-06-18T02:11:04Z

NAME                                              ROLE              AGE
rolebinding.rbac.authorization.k8s.io/read-pods   Role/pod-reader   27s
2.11.3.4 使用证书识别身份

生成ETCD证书:

参考:https://blog.csdn.net/BogerPeng/article/details/124892243
的 2.5.4 为 Etcd 自签证书
并把证书拷贝到该目录下

[root@k8smaster zhangsan]# pwd
/root/zhangsan
[root@k8smaster zhangsan]# ls
ca-config.json  ca.csr  ca-csr.json  ca-key.pem  ca.pem  rbac-user.sh

具体步骤:
注意参考错题合集,谢谢下文:

https://blog.csdn.net/qq_44792624/article/details/117332764

把生成的5个步骤合成一个sh文件 rbac-user.sh 在机器上运行

# rbac-user.sh, 也可以分步执行
cat > zhangsan-csr.json <<EOF
{
  "CN": "zhangsan",
  "hosts": [],
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "L": "BeiJing",
      "ST": "BeiJing"
    }
  ]
}
EOF


cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=www zhangsan-csr.json | cfssljson -bare zhangsan

kubectl config set-cluster kubernetes \
  --certificate-authority=ca.pem \
  --embed-certs=true \
  --server=https://192.168.226.141:6443 \
  --kubeconfig=zhangsan-kubeconfig
  
kubectl config set-credentials zhangsan \
  --client-key=zhangsan-key.pem \
  --client-certificate=zhangsan.pem \
  --embed-certs=true \
  --kubeconfig=zhangsan-kubeconfig
  
kubectl config set-context default \
  --cluster=kubernetes \
  --user=zhangsan \
  --kubeconfig=zhangsan-kubeconfig
  
kubectl config use-context default --kubeconfig=zhangsan-kubeconfig
[root@k8smaster zhangsan]# ls
ca-config.json  ca.csr  ca-csr.json  ca-key.pem  ca.pem  rbac-user.sh  zhangsan.csr  zhangsan-csr.json  zhangsan-key.pem  zhangsan-kubeconfig  zhangsan.pem

测试方法:

kubectl get pods -n roledemo --kubeconfig=./zhangsan-kubeconfig 
# 切换命名空间看输出结果区别

2.12 Ingress

也参考了:https://www.jianshu.com/p/595fd3fac7ff?ivk_sa=1024320u
感谢

2.12.1 概述

  • (1). 前面讲到的内容中,服务是:
把端口号对外暴露,通过ip+端口号进行访问
	使用Service里面的NodePort实现
  • (2). NodePort缺陷:
 在每个节点上都会起到端口,在访问的时候通过任何节点以ip+暴露端口号实现访问
 意味这每个端口号只能使用一次,一个端口对应一个应用
 实际访问中都是用域名,根据不同的域名跳转到不同的端口服务中
  • (3). Ingress和Pod的关系:
他们通过service关联
ingress作为统一入口,由service关联一组pod 

在这里插入图片描述

  • (4). ingress工作流程:
    在这里插入图片描述

2.12.2 使用ingress

这里选择官方维护的nginx控制器,实现部署

2.12.2.1 创建nginx应用, 对外暴露端口使用NodePort
  • 1). 创建名称为web的 deployment
[root@k8smaster admin]# kubectl create deployment web --image=nginx
deployment.apps/web created
######## NAME= web 的deployment
[root@k8smaster admin]# kubectl get deploy
NAME    READY   UP-TO-DATE   AVAILABLE   AGE
nginx   1/1     1            1           24d
web     1/1     1            1           29s
  • 2). 对外暴露端口
[root@k8smaster admin]# kubectl expose deployment web --port=80 --target-port=8080 --type=NodePort
service/web exposed
[root@k8smaster admin]# kubectl get svc
NAME         TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)        AGE
kubernetes   ClusterIP   10.96.0.1     <none>        443/TCP        24d
web          NodePort    10.103.17.3   <none>        80:31468/TCP   4s
2.12.2.2 部署 ingress Controller

创建文件 ingress-controller.yaml 并执行

# ingress-controller.yaml 
apiVersion: v1
kind: Namespace
metadata:
  name: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx

---

kind: ConfigMap
apiVersion: v1
metadata:
  name: nginx-configuration
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx

---
kind: ConfigMap
apiVersion: v1
metadata:
  name: tcp-services
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx

---
kind: ConfigMap
apiVersion: v1
metadata:
  name: udp-services
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx

---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: nginx-ingress-serviceaccount
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx

---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
  name: nginx-ingress-clusterrole
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
rules:
  - apiGroups:
      - ""
    resources:
      - configmaps
      - endpoints
      - nodes
      - pods
      - secrets
    verbs:
      - list
      - watch
  - apiGroups:
      - ""
    resources:
      - nodes
    verbs:
      - get
  - apiGroups:
      - ""
    resources:
      - services
    verbs:
      - get
      - list
      - watch
  - apiGroups:
      - ""
    resources:
      - events
    verbs:
      - create
      - patch
  - apiGroups:
      - "extensions"
      - "networking.k8s.io"
    resources:
      - ingresses
    verbs:
      - get
      - list
      - watch
  - apiGroups:
      - "extensions"
      - "networking.k8s.io"
    resources:
      - ingresses/status
    verbs:
      - update

---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: Role
metadata:
  name: nginx-ingress-role
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
rules:
  - apiGroups:
      - ""
    resources:
      - configmaps
      - pods
      - secrets
      - namespaces
    verbs:
      - get
  - apiGroups:
      - ""
    resources:
      - configmaps
    resourceNames:
      # Defaults to "<election-id>-<ingress-class>"
      # Here: "<ingress-controller-leader>-<nginx>"
      # This has to be adapted if you change either parameter
      # when launching the nginx-ingress-controller.
      - "ingress-controller-leader-nginx"
    verbs:
      - get
      - update
  - apiGroups:
      - ""
    resources:
      - configmaps
    verbs:
      - create
  - apiGroups:
      - ""
    resources:
      - endpoints
    verbs:
      - get

---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: RoleBinding
metadata:
  name: nginx-ingress-role-nisa-binding
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: nginx-ingress-role
subjects:
  - kind: ServiceAccount
    name: nginx-ingress-serviceaccount
    namespace: ingress-nginx

---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
  name: nginx-ingress-clusterrole-nisa-binding
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: nginx-ingress-clusterrole
subjects:
  - kind: ServiceAccount
    name: nginx-ingress-serviceaccount
    namespace: ingress-nginx

---

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-ingress-controller
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app.kubernetes.io/name: ingress-nginx
      app.kubernetes.io/part-of: ingress-nginx
  template:
    metadata:
      labels:
        app.kubernetes.io/name: ingress-nginx
        app.kubernetes.io/part-of: ingress-nginx
      annotations:
        prometheus.io/port: "10254"
        prometheus.io/scrape: "true"
    spec:
      hostNetwork: true
      # wait up to five minutes for the drain of connections
      terminationGracePeriodSeconds: 300
      serviceAccountName: nginx-ingress-serviceaccount
      nodeSelector:
        kubernetes.io/os: linux
      containers:
        - name: nginx-ingress-controller
          image: lizhenliang/nginx-ingress-controller:0.30.0
          args:
            - /nginx-ingress-controller
            - --configmap=$(POD_NAMESPACE)/nginx-configuration
            - --tcp-services-configmap=$(POD_NAMESPACE)/tcp-services
            - --udp-services-configmap=$(POD_NAMESPACE)/udp-services
            - --publish-service=$(POD_NAMESPACE)/ingress-nginx
            - --annotations-prefix=nginx.ingress.kubernetes.io
          securityContext:
            allowPrivilegeEscalation: true
            capabilities:
              drop:
                - ALL
              add:
                - NET_BIND_SERVICE
            # www-data -> 101
            runAsUser: 101
          env:
            - name: POD_NAME
              valueFrom:
                fieldRef:
                  fieldPath: metadata.name
            - name: POD_NAMESPACE
              valueFrom:
                fieldRef:
                  fieldPath: metadata.namespace
          ports:
            - name: http
              containerPort: 80
              protocol: TCP
            - name: https
              containerPort: 443
              protocol: TCP
          livenessProbe:
            failureThreshold: 3
            httpGet:
              path: /healthz
              port: 10254
              scheme: HTTP
            initialDelaySeconds: 10
            periodSeconds: 10
            successThreshold: 1
            timeoutSeconds: 10
          readinessProbe:
            failureThreshold: 3
            httpGet:
              path: /healthz
              port: 10254
              scheme: HTTP
            periodSeconds: 10
            successThreshold: 1
            timeoutSeconds: 10
          lifecycle:
            preStop:
              exec:
                command:
                  - /wait-shutdown

---

apiVersion: v1
kind: LimitRange
metadata:
  name: ingress-nginx
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
spec:
  limits:
  - min:
      memory: 90Mi
      cpu: 100m
    type: Container

执行结果:

[root@k8smaster ~]# kubectl apply -f ingress-controller.yaml 
namespace/ingress-nginx created
configmap/nginx-configuration created
configmap/tcp-services created
configmap/udp-services created
serviceaccount/nginx-ingress-serviceaccount created
clusterrole.rbac.authorization.k8s.io/nginx-ingress-clusterrole created
role.rbac.authorization.k8s.io/nginx-ingress-role created
rolebinding.rbac.authorization.k8s.io/nginx-ingress-role-nisa-binding created
clusterrolebinding.rbac.authorization.k8s.io/nginx-ingress-clusterrole-nisa-binding created
deployment.apps/nginx-ingress-controller created
limitrange/ingress-nginx created

查看 ingress controller 状态

[root@k8smaster ~]# kubectl get pod -n ingress-nginx
NAME                                       READY   STATUS    RESTARTS   AGE
nginx-ingress-controller-766fb9f77-5xqt8   1/1     Running   0          2m25s

2.12.2.3 创建 ingress 规则

创建 ingress-h.yaml 文件

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: example-ingress
spec:
  rules:
  - host: example.ingredemo.com
    http:
      paths:
      - path: /
        backend:
          serviceName: web
          servicePort: 80

执行 yaml 文件

[root@k8smaster ~]# kubectl apply -f ingress-h.yaml 
ingress.networking.k8s.io/example-ingress created

查看状态:
看到其部署在 192.168.226.143 k8sworker2

[root@k8smaster ~]# kubectl get pods -n ingress-nginx -o wide
NAME                                       READY   STATUS    RESTARTS   AGE   IP                NODE         NOMINATED NODE   READINESS GATES
nginx-ingress-controller-766fb9f77-5xqt8   1/1     Running   0          10m   192.168.226.143   k8sworker2   <none>           <none>

此时去 k8sworker2 查询,能看到80和443端口都被nginx监听
在这里插入图片描述

2.12.2.4 在windows系统hosts文件中添加域名访问规则

ingress-h.yaml中的 example.ingredemo.com
以及其部署的 192.168.226.143 k8sworker2
在这里插入图片描述

### 查看pod
[root@k8smaster ~]# kubectl get pods -n ingress-nginx
NAME                                       READY   STATUS    RESTARTS   AGE
nginx-ingress-controller-766fb9f77-5xqt8   1/1     Running   1          23h

### 查看 ingress
[root@k8smaster admin]# kubectl get ing
NAME              CLASS    HOSTS                   ADDRESS         PORTS   AGE
example-ingress   <none>   example.ingredemo.com   10.103.196.63   80      24h

### 查看该pod日志,反复出现报错信息   ###
[root@k8smaster ~]# kubectl logs nginx-ingress-controller-766fb9f77-5xqt8 -n ingress-nginx
W0619 15:57:01.529690       6 queue.go:130] requeuing &ObjectMeta{Name:sync status,GenerateName:,Namespace:,SelfLink:,UID:,ResourceVersion:,Generation:0,CreationTimestamp:0001-01-01 00:00:00 +0000 UTC,DeletionTimestamp:<nil>,DeletionGracePeriodSeconds:nil,Labels:map[string]string{},Annotations:map[string]string{},OwnerReferences:[]OwnerReference{},Finalizers:[],ClusterName:,ManagedFields:[]ManagedFieldsEntry{},}, err services "ingress-nginx" not found

如下:
在这里插入图片描述
解决方案参考链接如下,感谢:

链接1:  https://www.jianshu.com/p/67a086a3df2f?ivk_sa=1024320u
链接2:  https://github.com/kubernetes-sigs/kubespray/issues/3005

添加 ingress-nginx的svc即可:

## ingress-nginx.yaml
apiVersion: v1
kind: Service
metadata:
  name: ingress-nginx
  namespace: ingress-nginx
spec:
  type: ClusterIP
  ports:
  - name: http
    port: 80
    targetPort: 80
    protocol: TCP
  - name: https
    port: 443
    targetPort: 443
    protocol: TCP
  selector:
    app: ingress-nginx

结果:
在这里插入图片描述
在这里插入图片描述

会出现这样是因为 ingress-nginx 出现了无法获取到
http://10.244.1.75:8080/favicon.ico 这个图标的问题

10.244.1.75 是外网地址,我暂时访问不到,但不妨碍上面的验证。
这里mark一下,回头有空再填坑。
*13032 connect() failed (111: Connection refused) while connecting to upstream, 
client: 192.168.226.1, server: example.ingredemo.com, request: "GET /favicon.ico HTTP/1.1", 
upstream: "http://10.244.1.75:8080/favicon.ico", host: "example.ingredemo.com", referrer: "http://example.ingredemo.com/"
Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐