尚硅谷云原生学习笔记(144~172集)

笔记列表:

目录

144、k8s网络-为什么要使用Ingress网络_1

144.1、为什么需要Ingress?

  • Service可以使用NodePort暴露集群外访问端口,但是性能低下,并不安全
  • Ingress可以负载均衡、限流等
  • Ingress 公开了从集群外部到集群内服务的 HTTP 和 HTTPS 路由。 流量路由被Ingress 资源上定义的规则控制。
  • 我们使用Ingress作为整个集群统一的入口,配置Ingress规则转到对应的Service

144.2、整体框架图

在这里插入图片描述

145、k8s网络-Ingress网络架构_1

146、k8s网络-部署Ingress-nginx_1

146.1、获取安装yaml文件

首先点击Ingress查看官方文档

然后我们需要看一下ingress-nginx如何安装,在上面的文档中我们能找到如下内容点击下图红色方框中的蓝色链接就好,如下:

在这里插入图片描述

之后就进入了ingress-nginx的Installation Guide,然后往下滑动屏幕,之后就可以点击下面的Bare-metal进行安装了,如下:

在这里插入图片描述

然后就可以看到安装命令,但是在国内我们不能这样安装,我们把下图中的链接复制出来,在浏览器上访问就可以得到ingress-nginx的对应yaml文件

在这里插入图片描述

146.2、安装ingress-nginx

146.2.1、导入镜像

直接使用docker load -i 镜像tar包名称即可导入,镜像在下面

链接:https://pan.baidu.com/s/1ofsKDRWXuvhTFWmqlvHG1Q?pwd=uycg

提取码:uycg

146.2.2、修改yaml文件

官方文件地址:https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v0.46.0/deploy/static/provider/baremetal/deploy.yaml

我的文件在下面

1、修改service的type

在这里插入图片描述

2、修改kind类型

在这里插入图片描述

3、修改上图DaemonSet下面的网络为主机网络,即80和443端口直接占据的就是虚拟机的80和443端口;另外还修改了镜像地址,原因是那个镜像我们无法下载

在这里插入图片描述

4、修改节点选择方式,之前那种节点相当于是选择所有的节点,修改之后的节点选择器只会选择部分打标签的节点

在这里插入图片描述

146.2.3、执行yaml文件

所需yaml文件在下面,然后通过kubectl apply -f XXX.yaml命令执行就是了

apiVersion: v1
kind: Namespace
metadata:
  name: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/instance: ingress-nginx

---
# Source: ingress-nginx/templates/controller-serviceaccount.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  labels:
    helm.sh/chart: ingress-nginx-3.30.0
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/version: 0.46.0
    app.kubernetes.io/managed-by: Helm
    app.kubernetes.io/component: controller
  name: ingress-nginx
  namespace: ingress-nginx
automountServiceAccountToken: true
---
# Source: ingress-nginx/templates/controller-configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  labels:
    helm.sh/chart: ingress-nginx-3.30.0
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/version: 0.46.0
    app.kubernetes.io/managed-by: Helm
    app.kubernetes.io/component: controller
  name: ingress-nginx-controller
  namespace: ingress-nginx
data:
---
# Source: ingress-nginx/templates/clusterrole.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  labels:
    helm.sh/chart: ingress-nginx-3.30.0
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/version: 0.46.0
    app.kubernetes.io/managed-by: Helm
  name: 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:
      - extensions
      - networking.k8s.io   # k8s 1.14+
    resources:
      - ingresses
    verbs:
      - get
      - list
      - watch
  - apiGroups:
      - ''
    resources:
      - events
    verbs:
      - create
      - patch
  - apiGroups:
      - extensions
      - networking.k8s.io   # k8s 1.14+
    resources:
      - ingresses/status
    verbs:
      - update
  - apiGroups:
      - networking.k8s.io   # k8s 1.14+
    resources:
      - ingressclasses
    verbs:
      - get
      - list
      - watch
---
# Source: ingress-nginx/templates/clusterrolebinding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  labels:
    helm.sh/chart: ingress-nginx-3.30.0
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/version: 0.46.0
    app.kubernetes.io/managed-by: Helm
  name: ingress-nginx
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: ingress-nginx
subjects:
  - kind: ServiceAccount
    name: ingress-nginx
    namespace: ingress-nginx
---
# Source: ingress-nginx/templates/controller-role.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  labels:
    helm.sh/chart: ingress-nginx-3.30.0
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/version: 0.46.0
    app.kubernetes.io/managed-by: Helm
    app.kubernetes.io/component: controller
  name: ingress-nginx
  namespace: ingress-nginx
rules:
  - apiGroups:
      - ''
    resources:
      - namespaces
    verbs:
      - get
  - apiGroups:
      - ''
    resources:
      - configmaps
      - pods
      - secrets
      - endpoints
    verbs:
      - get
      - list
      - watch
  - apiGroups:
      - ''
    resources:
      - services
    verbs:
      - get
      - list
      - watch
  - apiGroups:
      - extensions
      - networking.k8s.io   # k8s 1.14+
    resources:
      - ingresses
    verbs:
      - get
      - list
      - watch
  - apiGroups:
      - extensions
      - networking.k8s.io   # k8s 1.14+
    resources:
      - ingresses/status
    verbs:
      - update
  - apiGroups:
      - networking.k8s.io   # k8s 1.14+
    resources:
      - ingressclasses
    verbs:
      - get
      - list
      - watch
  - apiGroups:
      - ''
    resources:
      - configmaps
    resourceNames:
      - ingress-controller-leader-nginx
    verbs:
      - get
      - update
  - apiGroups:
      - ''
    resources:
      - configmaps
    verbs:
      - create
  - apiGroups:
      - ''
    resources:
      - events
    verbs:
      - create
      - patch
---
# Source: ingress-nginx/templates/controller-rolebinding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  labels:
    helm.sh/chart: ingress-nginx-3.30.0
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/version: 0.46.0
    app.kubernetes.io/managed-by: Helm
    app.kubernetes.io/component: controller
  name: ingress-nginx
  namespace: ingress-nginx
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: ingress-nginx
subjects:
  - kind: ServiceAccount
    name: ingress-nginx
    namespace: ingress-nginx
---
# Source: ingress-nginx/templates/controller-service-webhook.yaml
apiVersion: v1
kind: Service
metadata:
  labels:
    helm.sh/chart: ingress-nginx-3.30.0
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/version: 0.46.0
    app.kubernetes.io/managed-by: Helm
    app.kubernetes.io/component: controller
  name: ingress-nginx-controller-admission
  namespace: ingress-nginx
spec:
  type: ClusterIP
  ports:
    - name: https-webhook
      port: 443
      targetPort: webhook
  selector:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/component: controller
---
# Source: ingress-nginx/templates/controller-service.yaml:不要
apiVersion: v1
kind: Service
metadata:
  annotations:
  labels:
    helm.sh/chart: ingress-nginx-3.30.0
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/version: 0.46.0
    app.kubernetes.io/managed-by: Helm
    app.kubernetes.io/component: controller
  name: ingress-nginx-controller
  namespace: ingress-nginx
spec:
  type: ClusterIP  ## 改为clusterIP
  ports:
    - name: http
      port: 80
      protocol: TCP
      targetPort: http
    - name: https
      port: 443
      protocol: TCP
      targetPort: https
  selector:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/component: controller
---
# Source: ingress-nginx/templates/controller-deployment.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
  labels:
    helm.sh/chart: ingress-nginx-3.30.0
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/version: 0.46.0
    app.kubernetes.io/managed-by: Helm
    app.kubernetes.io/component: controller
  name: ingress-nginx-controller
  namespace: ingress-nginx
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: ingress-nginx
      app.kubernetes.io/instance: ingress-nginx
      app.kubernetes.io/component: controller
  revisionHistoryLimit: 10
  minReadySeconds: 0
  template:
    metadata:
      labels:
        app.kubernetes.io/name: ingress-nginx
        app.kubernetes.io/instance: ingress-nginx
        app.kubernetes.io/component: controller
    spec:
      dnsPolicy: ClusterFirstWithHostNet   ## dns对应调整为主机网络
      hostNetwork: true  ## 直接让nginx占用本机80端口和443端口,所以使用主机网络
      containers:
        - name: controller
          image: ingress-nginx-controller:v0.46.0
          imagePullPolicy: IfNotPresent
          lifecycle:
            preStop:
              exec:
                command:
                  - /wait-shutdown
          args:
            - /nginx-ingress-controller
            - --election-id=ingress-controller-leader
            - --ingress-class=nginx
            - --configmap=$(POD_NAMESPACE)/ingress-nginx-controller
            - --validating-webhook=:8443
            - --validating-webhook-certificate=/usr/local/certificates/cert
            - --validating-webhook-key=/usr/local/certificates/key
          securityContext:
            capabilities:
              drop:
                - ALL
              add:
                - NET_BIND_SERVICE
            runAsUser: 101
            allowPrivilegeEscalation: true
          env:
            - name: POD_NAME
              valueFrom:
                fieldRef:
                  fieldPath: metadata.name
            - name: POD_NAMESPACE
              valueFrom:
                fieldRef:
                  fieldPath: metadata.namespace
            - name: LD_PRELOAD
              value: /usr/local/lib/libmimalloc.so
          livenessProbe:
            httpGet:
              path: /healthz
              port: 10254
              scheme: HTTP
            initialDelaySeconds: 10
            periodSeconds: 10
            timeoutSeconds: 1
            successThreshold: 1
            failureThreshold: 5
          readinessProbe:
            httpGet:
              path: /healthz
              port: 10254
              scheme: HTTP
            initialDelaySeconds: 10
            periodSeconds: 10
            timeoutSeconds: 1
            successThreshold: 1
            failureThreshold: 3
          ports:
            - name: http
              containerPort: 80
              protocol: TCP
            - name: https
              containerPort: 443
              protocol: TCP
            - name: webhook
              containerPort: 8443
              protocol: TCP
          volumeMounts:
            - name: webhook-cert
              mountPath: /usr/local/certificates/
              readOnly: true
          resources:
            requests:
              cpu: 100m
              memory: 90Mi
      nodeSelector:  ## 节点选择器
        node-role: ingress #以后只需要给某个node打上这个标签就可以部署ingress-nginx到这个节点上了
        #kubernetes.io/os: linux  ## 修改节点选择
      serviceAccountName: ingress-nginx
      terminationGracePeriodSeconds: 300
      volumes:
        - name: webhook-cert
          secret:
            secretName: ingress-nginx-admission
---
# Source: ingress-nginx/templates/admission-webhooks/validating-webhook.yaml
# before changing this value, check the required kubernetes version
# https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#prerequisites
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
  labels:
    helm.sh/chart: ingress-nginx-3.30.0
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/version: 0.46.0
    app.kubernetes.io/managed-by: Helm
    app.kubernetes.io/component: admission-webhook
  name: ingress-nginx-admission
webhooks:
  - name: validate.nginx.ingress.kubernetes.io
    matchPolicy: Equivalent
    rules:
      - apiGroups:
          - networking.k8s.io
        apiVersions:
          - v1beta1
        operations:
          - CREATE
          - UPDATE
        resources:
          - ingresses
    failurePolicy: Fail
    sideEffects: None
    admissionReviewVersions:
      - v1
      - v1beta1
    clientConfig:
      service:
        namespace: ingress-nginx
        name: ingress-nginx-controller-admission
        path: /networking/v1beta1/ingresses
---
# Source: ingress-nginx/templates/admission-webhooks/job-patch/serviceaccount.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: ingress-nginx-admission
  annotations:
    helm.sh/hook: pre-install,pre-upgrade,post-install,post-upgrade
    helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded
  labels:
    helm.sh/chart: ingress-nginx-3.30.0
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/version: 0.46.0
    app.kubernetes.io/managed-by: Helm
    app.kubernetes.io/component: admission-webhook
  namespace: ingress-nginx
---
# Source: ingress-nginx/templates/admission-webhooks/job-patch/clusterrole.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: ingress-nginx-admission
  annotations:
    helm.sh/hook: pre-install,pre-upgrade,post-install,post-upgrade
    helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded
  labels:
    helm.sh/chart: ingress-nginx-3.30.0
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/version: 0.46.0
    app.kubernetes.io/managed-by: Helm
    app.kubernetes.io/component: admission-webhook
rules:
  - apiGroups:
      - admissionregistration.k8s.io
    resources:
      - validatingwebhookconfigurations
    verbs:
      - get
      - update
---
# Source: ingress-nginx/templates/admission-webhooks/job-patch/clusterrolebinding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: ingress-nginx-admission
  annotations:
    helm.sh/hook: pre-install,pre-upgrade,post-install,post-upgrade
    helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded
  labels:
    helm.sh/chart: ingress-nginx-3.30.0
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/version: 0.46.0
    app.kubernetes.io/managed-by: Helm
    app.kubernetes.io/component: admission-webhook
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: ingress-nginx-admission
subjects:
  - kind: ServiceAccount
    name: ingress-nginx-admission
    namespace: ingress-nginx
---
# Source: ingress-nginx/templates/admission-webhooks/job-patch/role.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: ingress-nginx-admission
  annotations:
    helm.sh/hook: pre-install,pre-upgrade,post-install,post-upgrade
    helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded
  labels:
    helm.sh/chart: ingress-nginx-3.30.0
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/version: 0.46.0
    app.kubernetes.io/managed-by: Helm
    app.kubernetes.io/component: admission-webhook
  namespace: ingress-nginx
rules:
  - apiGroups:
      - ''
    resources:
      - secrets
    verbs:
      - get
      - create
---
# Source: ingress-nginx/templates/admission-webhooks/job-patch/rolebinding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: ingress-nginx-admission
  annotations:
    helm.sh/hook: pre-install,pre-upgrade,post-install,post-upgrade
    helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded
  labels:
    helm.sh/chart: ingress-nginx-3.30.0
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/version: 0.46.0
    app.kubernetes.io/managed-by: Helm
    app.kubernetes.io/component: admission-webhook
  namespace: ingress-nginx
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: ingress-nginx-admission
subjects:
  - kind: ServiceAccount
    name: ingress-nginx-admission
    namespace: ingress-nginx
---
# Source: ingress-nginx/templates/admission-webhooks/job-patch/job-createSecret.yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: ingress-nginx-admission-create
  annotations:
    helm.sh/hook: pre-install,pre-upgrade
    helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded
  labels:
    helm.sh/chart: ingress-nginx-3.30.0
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/version: 0.46.0
    app.kubernetes.io/managed-by: Helm
    app.kubernetes.io/component: admission-webhook
  namespace: ingress-nginx
spec:
  template:
    metadata:
      name: ingress-nginx-admission-create
      labels:
        helm.sh/chart: ingress-nginx-3.30.0
        app.kubernetes.io/name: ingress-nginx
        app.kubernetes.io/instance: ingress-nginx
        app.kubernetes.io/version: 0.46.0
        app.kubernetes.io/managed-by: Helm
        app.kubernetes.io/component: admission-webhook
    spec:
      containers:
        - name: create
          image: docker.io/jettech/kube-webhook-certgen:v1.5.1
          imagePullPolicy: IfNotPresent
          args:
            - create
            - --host=ingress-nginx-controller-admission,ingress-nginx-controller-admission.$(POD_NAMESPACE).svc
            - --namespace=$(POD_NAMESPACE)
            - --secret-name=ingress-nginx-admission
          env:
            - name: POD_NAMESPACE
              valueFrom:
                fieldRef:
                  fieldPath: metadata.namespace
      restartPolicy: OnFailure
      serviceAccountName: ingress-nginx-admission
      securityContext:
        runAsNonRoot: true
        runAsUser: 2000
---
# Source: ingress-nginx/templates/admission-webhooks/job-patch/job-patchWebhook.yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: ingress-nginx-admission-patch
  annotations:
    helm.sh/hook: post-install,post-upgrade
    helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded
  labels:
    helm.sh/chart: ingress-nginx-3.30.0
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/version: 0.46.0
    app.kubernetes.io/managed-by: Helm
    app.kubernetes.io/component: admission-webhook
  namespace: ingress-nginx
spec:
  template:
    metadata:
      name: ingress-nginx-admission-patch
      labels:
        helm.sh/chart: ingress-nginx-3.30.0
        app.kubernetes.io/name: ingress-nginx
        app.kubernetes.io/instance: ingress-nginx
        app.kubernetes.io/version: 0.46.0
        app.kubernetes.io/managed-by: Helm
        app.kubernetes.io/component: admission-webhook
    spec:
      containers:
        - name: patch
          image: docker.io/jettech/kube-webhook-certgen:v1.5.1
          imagePullPolicy: IfNotPresent
          args:
            - patch
            - --webhook-name=ingress-nginx-admission
            - --namespace=$(POD_NAMESPACE)
            - --patch-mutating=false
            - --secret-name=ingress-nginx-admission
            - --patch-failure-policy=Fail
          env:
            - name: POD_NAMESPACE
              valueFrom:
                fieldRef:
                  fieldPath: metadata.namespace
      restartPolicy: OnFailure
      serviceAccountName: ingress-nginx-admission
      securityContext:
        runAsNonRoot: true
        runAsUser: 2000

146.2.4、修改节点的标签,让ingress-nginx部署到对应节点

只要执行下面的命令之后,对应的节点上就会部署ingress-nginx

kubectl label node 节点名称 node-role=ingress

可以通过kubectl get ds -A去查看部署情况,可以看到有一台机器上部署了ingress-nginx

在这里插入图片描述

146.2.5、如何从浏览器访问ingress-nginx

一图胜千言,根据节点选择,可以让ingress-nginx部署到部分节点中,然后我们说一下流量走向,从外部访问的流量到达F5硬件层面的负载均衡器,之后流量就会被打到部署ingress-nginx的节点上(直接使用ingress-nginx所在节点的ip进行负载均衡即可,另外ingress-nginx用的80和443端口是节点所在虚拟机的主机ip),然后ingress-nginx在根据规则将流量达到service中,只有service在将流量打到具体执行业务的Pod中

在这里插入图片描述

147、k8s网络-Ingress示例_1

首先先说下面的yaml文件,it666.com是我随意起的名字,pathType: Prefix代表按照前缀匹配,path: /代表前缀是/就行,backend.service.name: canary-service-test代表到达ingress-nginx的流量会分配到canary-service-test这个service里面,并且对应的service端口是80,我们只需要在windows中的hosts文件中配置上node2节点的虚拟机ip和it666.com的关联关系就可以了,例如:192.168.139.134 it666.com,之后我们在浏览器中直接访问http://it666.com(访问之后,链接后面会默认带/)就可以看到nginx的结果页了,并且也能看到负载均衡的效果

既然已经提到了匹配方式,那就大致介绍一下吧

  • Prefix:前缀匹配
  • Exact:精确匹配

这些匹配方式的详细解释,以及详细用法都可以通过官网去学习

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: it666-ingress
  namespace: default
spec:
  rules:
  - host: it666.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:  ## 指定需要响应的后端服务
          service:
            name: canary-service-test  ## kubernetes集群的svc名称
            port:
              number: 80  ## service的端口号

148、k8s网络-Ingress细节配置-默认服务_1

记得在hosts文件中配置192.168.139.134 it672.com,基本情况不需要解释了,说一下效果吧,我们访问http://it672.com/abc看到的是下图效果

在这里插入图片描述
如果访问http://it672.com,那么看到的是下图效果

在这里插入图片描述

所以如果访问的内容不匹配,那就会访问默认服务,其中defaultBackend.service.name访问的是默认服务的名称,而defaultBackend.service.port.number访问的是默认服务service中的端口

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: it672-ingress
  namespace: default
spec:
  defaultBackend:  ## 指定所有未匹配的默认后端
    service:
      name: php-apache
      port: 
        number: 80
  rules:
  - host: it672.com
    http:
      paths:
      - path: /abc
        pathType: Prefix
        backend:
          service:
            name: canary-service-test
            port:
              number: 80

149、k8s网络-nginx-ingress的全局配置_1

首先我们需要知道可以修改哪些全局配置,点击ConfigMaps就可以去查看了,然后还给了配置示例,如下:

data:
  map-hash-bucket-size: "128"
  ssl-protocols: SSLv2

具体配置效果是这样的,如下:

在这里插入图片描述

我们可以通过下面的命令去进行配置,保存就可以更新配置了,如果配置没有更新,那就把那两个ingress-nginx的Pod删除了,让它自己生成就可以应用最新配置了

kubectl edit cm ingress-nginx-controller -n  ingress-nginx

150、k8s网络-ingress限流等示例_1

正常访问http://it777.com/abc都是没问题的,但是我们持续点击F5按键,那就会出现下面内容:

在这里插入图片描述
原因就是被限流拦截了

既然已经看完了效果,那就来看一下yaml文件吧,其实我们只添加了一个metadata.annotations.nginx.ingress.kubernetes.io/limit-rps: "1",这个作用就是限制1s中之内只能访问一次

想了解更多注解用法的,请看:https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: it777-ingres
  namespace: default
  annotations:  ##注解
    nginx.ingress.kubernetes.io/limit-rps: "1"   ### 限流的配置
spec:
  rules:
  - host: it777.com
    http:
      paths:
      - path: /abc
        pathType: Prefix
        backend:
          service:
            name: canary-service-test
            port:
              number: 80

151、k8s网络-ingress-nginx部署特点_1

在安装ingress-nginx的yaml文件中,我们看到默认的标签选择节点的方式是可以给每一个机器部署ingress-nginx,但是后来我们更改之后就会让只有特定标签的节点才会安装ingress-nginx

在这里插入图片描述

152、k8s网络-ingress-路径重写示例_1

下面就是yaml文件,我们直接访问http://it888.com/api/hello,看到的内容如下:

在这里插入图片描述

从上面可以看出/api已经被截取掉了,只留下了/hello,所以达到了截串的目的

想了解更多注解用法的,请看:https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$2  ### 访问service的时候只会留下/api/后面的部分,官方链接:https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#rewrite
  name: it888-rewrite-ingress
  namespace: default
spec:
  rules: 
  - host: it888.com
    http:
      paths:
      - backend:
          service: 
            name: php-apache
            port: 
              number: 80
        path: /api(/|$)(.*)
        pathType: Prefix

153、k8s网络-ingress-基于Cookie的会话保持技术_1

在这里插入图片描述

想了解更多注解用法的,请看:https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: it999-ingress
  namespace: default
  annotations:
    nginx.ingress.kubernetes.io/affinity: "cookie" # 官方链接:https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#cookie-affinity
    nginx.ingress.kubernetes.io/session-cookie-name: "atguigu-session" # 如果不写该注解,那么默认名称是INGRESSCOOKIE
spec:
  rules:
  - host: it999.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: canary-service-test
            port:
              number: 80

154、k8s网络-ingress-安全连接_1

154.1、生成密钥文件

具体命令是:

openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout ${KEY_FILE_NAME} -out ${CERT_FILE_NAME} -subj "/CN=${公司域名}/O=${公司域名}"

例如:

openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.cert -subj "/CN=it666.com/O=it666.com"

说明:

其中${XXX}中的名称都是可以改变的,上面例子的含义是生成遵守x509规范的密钥,有效期是365天,加密算法是rsa:2048,生成的密钥key文件名称是tls.key,而密钥value的文件名称是tls.cert,然后公司的域名是it666.com

154.2、生成secret

具体命令是:

kubectl create secret tls ${secret名称} --key ${KEY_FILE_NAME} --cert ${CERT_FILE_NAME}

例子:

kubectl create secret tls it666-tls --key tls.key --cert tls.cert

说明:

其中kubectl create secret tls是定死的,而it666-tls是我们自己起的secret名称,而tls.keytls.cert和上一步生成的两个文件名称一一对应

拓展:

如果想看secret在哪里,我们可以通过命令kubectl get secret去查看

在这里插入图片描述

154.3、使用说明

对应yaml文件就在下面了,在浏览器上可以访问https://it666.com/abcd就可以了,可以看到效果就是有证书(虽然证书无效,但是证书依然使用上了)

在这里插入图片描述

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: it100-ingress
  namespace: default
spec:
  tls:
   - hosts:
     - it666.com # 公司域名
     secretName: it666-tls # secret名称
  rules:
  - host: it666.com
    http:
      paths:
      - path: /abcd
        pathType: Prefix
        backend:
          service:
            name: canary-service-test
            port:
              number: 80

155、k8s网站-ingress-几种证书的区别_1

证书分级(安全性从上往下依次增强):

  • DV:域名验证型证书
  • OV:企业验证型证书
  • EV:增强验证型证书

详细分级请看:科普:SSL证书中DV证书,OV证书和EV证书的特点与区别

156、k8s网络-ingress-金丝雀_1

156.1、service和ingress金丝雀版本对比

  • service金丝雀灰度发布版本(请看:129.2、金丝雀部署示例):service通过标签labels选择Pod来完成灰度发布
    在这里插入图片描述

  • ingress金丝雀灰度发布版本:使用不同ingress选择不同service,进而选择不同Pod来完成灰度发布
    在这里插入图片描述

156.2、ingress金丝雀版本部署示例

156.2.1、service和deployment示例(先执行)

说明:

用于生成两个service,2个deployment,并且service和其中一个deployment对应,未来我们的ingress来把流量达到service中,进而把流量分配到Pod中

其中访问canary-v1-service的结果是nginx默认页,而canary-v2-service的结果是111111111

首先:

直接使用docker load -i 镜像tar包名称即可导入,镜像在下面

链接:https://pan.baidu.com/s/1CBOrbuTBBJSa15xl7lMlsQ?pwd=kqgx

提取码:kqgx

其次执行yaml文件:

apiVersion: v1
kind: Service
metadata:
  name: canary-v1-service
  namespace: default
spec:
  selector:
    app: canary-v1-pod
  type: ClusterIP
  ports:
  - name: http
    port: 80
    targetPort: 80
    protocol: TCP
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name:  canary-v1-deploy
  namespace: default
  labels:
    app:  canary-v1-deploy
spec:
  selector:
    matchLabels:
      app: canary-v1-pod
  replicas: 1
  template:
    metadata:
      labels:
        app:  canary-v1-pod
    spec:
      containers:
      - name:  nginx
        image:  nginx
---
apiVersion: v1
kind: Service
metadata:
  name: canary-v2-service
  namespace: default
spec:
  selector:
    app: canary-v2-pod
  type: ClusterIP
  ports:
  - name: http
    port: 80
    targetPort: 80
    protocol: TCP
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name:  canary-v2-deploy
  namespace: default
  labels:
    app:  canary-v2-deploy
spec:
  selector:
    matchLabels:
      app: canary-v2-pod
  replicas: 1
  template:
    metadata:
      labels:
        app:  canary-v2-pod
    spec:
      containers:
      - name:  nginx
        image:  nginx-test:env-msg

156.2.2、ingress普通版本示例(中间执行)

说明:

普通版本对应canary-v1-service这个service

操作:

执行kubectl apply -f XXX.yaml即可,其中yaml文件就在下面

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: canary-v1-ingress
  namespace: default
spec:
  rules:
  - host: it110.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: canary-v1-service
            port:
              number: 80

156.2.3、ingress金丝雀版本示例(最后执行)

  • 想了解金丝雀版本的更多用法,请看:https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#canary
  • 注解nginx.ingress.kubernetes.io/canary的作用:在上面ingress普通版本示例中,我们看到这两个spec中的内容都是相同的,不过我们执行下面yaml文件的时候没有报错,原因是我们通过nginx.ingress.kubernetes.io/canary: "true"注解指明了当前ingress版本是金丝雀版本,用以完成灰度发布功能,所以执行过程中不会报错
  • 三个注解的优先级对比:分别是nginx.ingress.kubernetes.io/canary-by-header > nginx.ingress.kubernetes.io/canary-by-cookie > nginx.ingress.kubernetes.io/canary-weight,对于这三个注解而言,虽然多个优先级的可以并存,但是高优先级注解执行之后就不会执行低优先级的注解了
  • 注解nginx.ingress.kubernetes.io/canary-by-header:如果我们这样写,那么流量都会到ingress金丝雀版本中,不会到ingress普通版本中,postman中访问方式如下。如果你认为value值不想用always或者never判断,那就可以用nginx.ingress.kubernetes.io/canary-by-header-value来指定你认可的值,当value中是该值的时候,流量就会全部打到ingress金丝雀版本中
    在这里插入图片描述
  • 注解nginx.ingress.kubernetes.io/canary-by-cookie:如果我们这样写,那么流量都会到ingress金丝雀版本中,不会到ingress普通版本中,postman中访问方式如下
    在这里插入图片描述
  • 注解nginx.ingress.kubernetes.io/canary-weight:如果我们这样写,那么流量的80%都会到ingress金丝雀版本中,另外20%会到ingress普通版本中,postman中访问方式如下
    在这里插入图片描述
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: canary-v2-ingress
  namespace: default
  annotations:
    nginx.ingress.kubernetes.io/canary: "true" # 值为true表示当前ingress是金丝雀版本
    nginx.ingress.kubernetes.io/canary-by-header: "v2_header" # canary-by-header方式,如果对应值是always,那么始终将流量分配到这,如果值为never,那么作用相反
    nginx.ingress.kubernetes.io/canary-by-cookie: "v2_cookie" # canary-by-cookie方式,如果对应值是always,那么始终将流量分配到这,如果值为never,那么作用相反
    nginx.ingress.kubernetes.io/canary-weight: "80" # canary-weight方式,使用比率来控制分配到该ingress中的流量,其中0~100之间都是可用的
spec:
  rules:
  - host: it110.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: canary-v2-service
            port:
              number: 80

157、k8s网络-networkpolicy-网络隔离策略_1

157.1、网络隔离策略的简介

  • 概念:既可以用入站规则限制别人访问Pod,也可以用出站规则限制Pod访问别人
  • 网络隔离策略是名称空间下的资源吗?:是
  • 标识符:全名称是NetworkPolicy,缩写是netpol
  • 适用资源:Pod
  • 出入站规则:
    • 入站规则:限制别人访问Pod
    • 出站规则:限制Pod访问别人
  • 策略分类(适用于入站规则和出站规则):
    • 基于Pod的标签
    • 基于名称空间的标签
    • 基于网络范围
      在这里插入图片描述

157.2、使用示例

使用的yaml就在下面,先把里面的标签选择规则改成自己的,在用kubectl apply -f XXX.yaml执行就是了,然后按照下面的例子我们说一下测试方式,就测试一个入站规则吧,我们找到标签中app=busybox的Pod,然后进入该Pod。之后找到标签中app=nginx的Pod,复制下该Pod的ip,然后在上面busybox的容器中进行访问就好了;下面我们对yaml文件中的属性进行说明,如下所示:

  • podSelector:根据Pod的标签选中需要应用网络隔离策略的Pod
  • policyTypes:说明使用的是入站规则还是出站规则,默认是Ingress入站规则
  • ingress:定义入站白名单,也就是谁可以访问该Pod。然后可以通过ip范围、名称空间标签、Pod标签3种方式进行限制,3种方式可以并存,下面说一下3种网络隔离策略使用方式
    • 任何一个成立都行:下面例子中的写法,属于或者的关系,也就是任何一个成立都是可以访问的
    • 必须全满足:如果我们把namespaceSelectorpodSelector中的- 去掉,那就变成了交集,也就是必须满足这3种网络隔离策略才能访问nginx
      在这里插入图片描述
  • egress:定义出站白名单,也就是该Pod可以访问谁。然后可以通过ip范围、名称空间标签、Pod标签3种方式进行限制,3种方式可以并存,上面已经说了3种网络隔离策略使用方式,这里不再赘述
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: network-policy-test
  namespace: default
spec:
  podSelector:  ## 根据标签选中Pod,一旦这些Pod被选中,它们的网络策略将由下面出入站规则policyTypes控制
    matchLabels:
      app: nginx  # app是标签键,而nginx是标签值
  policyTypes:  ## 定义上面Pod的入站出站规则,默认值是Ingress;其中Ingress代表入站规则,Egress代表出站规则,可以只写一个
  - Ingress
  - Egress
  ingress:    ## 定义入站白名单,也就是限制谁可以访问该Pod
  - from:   
    - ipBlock: # ip方式
        cidr: 10.101.0.0/16 # 允许的范围,范围是10.101.0.0~10.101.255.255
        except: # 不被允许的IP范围,范围是10.101.1.0~10.101.1.255
        - 10.101.1.0/24
    - namespaceSelector:  # 名称空间的标签选择方式,查看标签名称是kubectl get ns --show-labels
        matchLabels:
          kubernetes.io/metadata.name: default # kubernetes.io/metadata.name是名称空间的标签键,而default是名称空间的标签值
    - podSelector:  # Pod的标签选择方式
        matchLabels:
          app: busybox # app是Pod的标签键,而busybox是Pod的标签值
    ports: # 设置可以访问的端口和协议
    - protocol: TCP
      port: 80
  egress:  ## 定义出站白名单,也就是限制该Pod可以访问谁
  - to: # 下面同样可以配置ipBlock、namespaceSelector、podSelector三种网络隔离策略,不过上面已经介绍过了,这里不再赘述
    - ipBlock:
        cidr: 10.101.0.0/16
    ports: # 设置可以访问的端口和协议
    - protocol: TCP
      port: 80

158、k8s网络-k8s网络小结_1

158.1、访问架构图

在这里插入图片描述
流程解释:

流量从客户端出发,经过DNS到达我们的负载均衡器(比如F5硬件负载均衡器),之后根据负载均衡规则,流量到达安装有Ingress的虚拟机上,Ingress根据规则把流量打到Service中,然后Service在根据自己的负载均衡策略将流量打到对应的Pod中,最终由Pod中的容器进行请求处理

158.2、访问流程

上面用文字做了简单解释,下面在用图来解释一下

在这里插入图片描述

158.3、网络互通原理

158.3.1、容器——>容器

解释: 一个Pod内部直接使用本地回路(loopback)通信

在这里插入图片描述

158.3.2、Pod——>Pod(同节点)

解释: Pod1访问Pod2,从Pod1的网卡出发到虚拟机的网卡,两者存在一个绑定关系,虚拟机的网卡当然也不能处理,那就通过网桥进行转发,网桥根据CIDR(网络范围)将请求转换到另外一个Pod了

在这里插入图片描述

158.3.3、Pod——>Pod(跨节点)

解释: Pod1访问Pod4,它们在不同的虚拟机上,从Pod1的网卡触发到VM1虚拟机的网卡,然后网卡把请求转给VM1虚拟机的网桥,网桥根据CIDR(网络范围)发现自己不能处理,然后它就去把请求发送到能处理它的另外一个虚拟机VM2,然后VM2接收之后通过网桥》虚拟机网卡,最终把流量送到了Pod4

在这里插入图片描述

158.3.4、Pod——>Service

解释: Pod1通过Pod网卡到虚拟机网卡,然后虚拟机网卡把请求转到网桥,网桥去查询IPtables/ipvs,找到合适的Ip之后在去把请求传给Pod

在这里插入图片描述

158.3.5、Service——>Pod

解释: 也是需要IPtables/ipvs的介入才能把请求转到对应的Pod

在这里插入图片描述

158.3.6、Pod——>Internet

在这里插入图片描述

158.3.7、Pod——>Internet(负载均衡,4层模型)

在这里插入图片描述

158.3.8、Pod——>Internet(Ingress,7层模型)

在这里插入图片描述

159、k8s网络-kube-proxy来控制节点直接网络_1

kubeproxy负载将所有节点的IP信息进行同步,所以我们访问任何一个节点都是OK的

160、k8s存储-卷的基本概念_1

160.1、卷挂载含义

  • 概念:容器说自己需要把一些东西挂到外边,Pod帮它来实现这个构思,最终完成卷挂载
  • 精髓:容器声明卷挂载,也就是哪些位置需要挂载出去;Pod声明卷详情,也就是说卷的位置到底在哪里。这些精髓都是可以落脚到yaml文件中
  • 绘图说明:下图可以来说明,其中volumeMounts对应容器中的卷挂载声明,而volumes对应Pod的卷详情说明,这两个属性就是yaml文件中用到的属性

在这里插入图片描述

161.2、卷挂载类型概览

  • 配置信息
    • Secret:用来保存敏感配置信息。Base64加密配置信息,一般是用户名、密码之类的敏感信息,比如我们阿里云连接信息就可以是Secret类型的
    • ConfigMap:用来保存普通配置信息。根据云原生12要素中所说,配置应该和应用分离,比如我们的微服务应用的application.properties配置就可以放在ConfigMap中,然后随时修改随时生效
  • 临时存储
    • emptyDir:绝对临时存储;随Pod而生,随Pod而死,在Pod中随便找的一个空目录
    • hostPath:相对临时存储;内容会存储到虚拟机本地,但是即使Pod死了,也不会删除hostPath的内容,不过如果Pod在别的虚拟机上拉起,这些数据也肯定找不到,毕竟其他机器上没有这些内容
  • 持久化存储
    • glusterFS
    • nfs
    • cephfs
    • ……

更多卷挂载信息请看:https://kubernetes.io/docs/concepts/storage/volumes/

在这里插入图片描述

161、k8s存储-Secret的创建_1

161.1、基本介绍

  • Secret对象类型用来保存敏感信息,例如密码、OAuth 令牌和 SSH 密钥。 将这些信息放在 secret 中比放在 Pod 的定义或者 容器镜像 中来说更加安全(他人不可见)和灵活(修改很方便)。
  • Secret 是一种包含少量敏感信息例如密码、令牌或密钥的对象。用户可以创建 Secret,同时系统也创建了一些 Secret。
  • 官方文档:https://kubernetes.io/zh-cn/docs/concepts/configuration/secret/

161.2、secret种类

161.2.1、普通划分方法

  • docker-registry:创建一个给 Docker registry 使用的 secret。在配置连接阿里云镜像仓库密钥的时候用过,详情请看:104.2、如何从私有镜像仓库下载镜像
  • tls:创建一个 TLS secret。在配置ingress安全连接的时候用过,详情请看:154.2、生成secret
  • generic:从本地 file, directory 或者 literal value 创建一个 secret。这个下面会讲到

在这里插入图片描述

161.2.2、细致划分方法

说明: 可以通过kubectl get secrets 资源名称 -oyaml 查看详情类型type,比如kubectl get secrets my-aliyun -oyaml,例如:

在这里插入图片描述

更多内置类型请看下面表格:

在这里插入图片描述

161.3、创建secret用法

说明: docker-registrytls类型的情况之前都已经讲过了,这里不再赘述,所以下面只说明generic的用法

161.3.1、普通字符串

命令方式:

# kubectl create secret generic是定死的,而mysql-secret是secret的名称
# username是key,value是root,并且password是key,value是123456,用命令创建的方式中的value值都是明文
kubectl create secret generic mysql-secret \
  --from-literal=username='root' \
  --from-literal=password='123456'

yaml文件方式:

注意:usernamepassword的值都是经过Base64加密算法进行加密过后的写法

apiVersion: v1
kind: Secret
metadata:
  name: mysql-secret
data:
  username: cm9vdA==
  password: MTIzNDU2

161.3.2、文件内容

161.3.2.1、默认键名(键名是文件名称)

命令方式:

# 首先新建两个文件,分别是username.txt和password.txt,并且里面放置的内容分别是root、123456
kubectl create secret generic mysql_secret_file \
  --from-file=./username.txt \
  --from-file=./password.txt

yaml文件方式:

注意:username.txtpassword.txt的值都是经过Base64加密算法进行加密过后的写法

apiVersion: v1
kind: Secret
metadata:
  name: mysql_secret_file
data:
  username.txt: cm9vdAo=
  password.txt: MTIzNDU2Cg==

161.3.2.1、指定键名

命令方式:

# kubectl create secret generic是定死的,而mysql_secret_file_02是secret的名称
# username是key,value是username.txt内容,并且password是key,value是password.txt内容
kubectl create secret generic mysql_secret_file_02 \
  --from-file=username=./username.txt \
  --from-file=password=./password.txt

yaml文件方式:

注意:usernamepassword的值都是经过Base64加密算法进行加密过后的写法

apiVersion: v1
kind: Secret
metadata:
  name: mysql_secret_file_02
data:
  username: cm9vdAo=
  password: MTIzNDU2Cg==

162、k8s存储-secret使用Pod.env进行获取-不会热更新_1

以下yaml文件中包含3种可以动态获取配置的方式,分别是secretKeyRef(从secret资源中获取键值)、fieldRef(从yaml文件中动态获取属性值)、resourceFieldRef(从yaml文件的pod资源配置中获取resource资源信息)

测试的时候我们需要进入busybox容器,命令是:kubectl exec -it pod-use-secret-test -- /bin/sh,如下所示:

在这里插入图片描述

我们即使更新了secret资源中的键值,但是也不会更改已经运行的容器中的变量值,所以这也被称作不会热更新

下面是测试用的yaml文件:

apiVersion: v1
kind: Pod
metadata:
  name: "pod-use-secret-test"
  namespace: default
  labels:
    app: "pod-use-secret-test"
spec:
  containers:
  - name: pod-use-secret-test
    image: "busybox"
    command: ['/bin/sh', '-c', 'sleep 3600']
    resources:
      limits:
        cpu: 200m
        memory: 500Mi
      requests:
        cpu: 100m
        memory: 200Mi
    env:
    - name: username # 在容器中可以用$username方式调用
      valueFrom:
        secretKeyRef: # 1、secret
          name: mysql-secret # secret资源名称
          key: username # 键名称
    - name: namespace # 在容器中可以用$namespace方式调用
      valueFrom:
        fieldRef: # 2、field
          fieldPath: metadata.namespace # 来自上面属性字段的全路径
    - name: limitcpu # 在容器中可以用$limitcpu方式调用
      valueFrom:
        resourceFieldRef: # 3、resource
          containerName: pod-use-secret-test # 上面pod的名称
          resource: limits.cpu # 上面pod资源的一些限制信息,可以填写的内容比如有:limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage

上面那几种配置方式都来自于kubectl explain命令所得,如下所示:

在这里插入图片描述

163、k8s存储-secret挂载的方式使用_1

163.1、将secret中的所有键值都以文件的方式挂载进去,其中键为文件名,值为文件内容

apiVersion: v1
kind: Pod
metadata:
  name: "pod-secret-volume-all-test"
  namespace: default
  labels:
    app: "pod-secret-volume-all-test"
spec:
  containers:
  - name: pod-secret-volume-all-test
    image: "busybox"
    command: ['/bin/sh', '-c', 'sleep 3600']
    volumeMounts: # 在容器中声明挂载信息
    - name: app
      mountPath: /app
  volumes: # 指定挂载详情
  - name: app
    secret: # 以secret方式挂载,这只是其中一种,还可以是configMap、cephfs、nfs、hostPath等
      secretName: mysql-secret # secret资源名称,下面不加items属性,这种会挂载所有文件(键为名,值为文件内容)到容器指定位置

进入busybox看一下效果吧,如下:

在这里插入图片描述

163.2、将secret中的部分键值以文件的方式挂载进去,其中键名是我们自己指定的,值为文件内容

apiVersion: v1
kind: Pod
metadata:
  name: "pod-secret-volume-items-test"
  namespace: default
  labels:
    app: "pod-secret-volume-items-test"
spec:
  containers:
  - name: pod-secret-volume-items-test
    image: "busybox"
    command: ['/bin/sh', '-c', 'sleep 3600']
    volumeMounts: # 在容器中声明挂载信息
    - name: app
      mountPath: /app
  volumes: # 指定挂载详情
  - name: app
    secret: # 以secret方式挂载,这只是其中一种,还可以是configMap、cephfs、nfs、hostPath等
      secretName: mysql-secret # secret资源名称
      items:
      - key: username # secret中的键名
        path: info/username.txt # 必须是相对路径,否则会报错

进入busybox看一下效果吧,如下:

在这里插入图片描述

164、k8s存储-secret挂载默认只读_1

secret资源挂载到容器内部默认是只读的,不能从容器内部进行修改。如果真的想从容器内部修改,那就需要考虑我们进入容器时的权限问题,其中挂载到容器内部的secret资源的权限值得是Pod外部的用户权限,即使我们在容器内部是root用户,但是依然无法修改容器内的secret挂载资源

在这里插入图片描述

165、k8s存储-cm结合SpringBoot做到生产配置无感知_1

165.1、创建ConfigMap

165.1.1、普通字符串

命令方式:

kubectl create configmap my-config \
 --from-literal=username=root \
 --from-literal=password=123456

yaml方式:

apiVersion: v1
kind: ConfigMap
metadata:
  name: my-config
data:
  username: root
  password: "123456"

165.1.2、类似文件

165.1.2.1、默认键名(键名是文件名称)

命令方式:

 kubectl create configmap my-config-file \
 --from-file=username.txt \
 --from-file=password.txt

yaml方式:

apiVersion: v1
kind: ConfigMap
metadata:
  name: my-config-file
data:
  username.txt: | # 键名就是文件名称,键值是文件内容
    root
  password.txt: |
    123456

165.1.2.2、指定键名

命令方式:

kubectl create configmap my-config-file-1 \
--from-file=username=username.txt \
--from-file=password=password.txt

yaml方式:

apiVersion: v1
kind: ConfigMap
metadata:
  name: my-config-file-1
data:
  username: | # 键名是我们指定的名称,键值是文件内容
    root
  password: |
    123456

165.2、使用ConfigMap

165.2.1、Pod中env环境变量

apiVersion: v1
kind: Pod
metadata:
  name: "pod-use-configmap-test"
  namespace: default
  labels:
    app: "pod-use-configmap-test"
spec:
  containers:
  - name: pod-use-configmap-test
    image: "busybox"
    command: ['/bin/sh', '-c', 'sleep 3600']
    env:
    - name: username # 在容器中可以用$username方式调用
      valueFrom:
        configMapKeyRef: # configMap类型,可以对比之前说过的secret(加密信息)、fieldRef(字段属性)、resourceFieldRef(Pod中的resource资源)
          name: my-config # configMap资源名称
          key: username # 键名称

进入busybox看一下效果吧,如下:

在这里插入图片描述

165.2.2、将ConfigMap中的配置信息挂载到容器内部

165.2.2.1、挂载ConfigMap中的全部键值

apiVersion: v1
kind: Pod
metadata:
  name: "pod-configmap-volume-all-test"
  namespace: default
  labels:
    app: "pod-configmap-volume-all-test"
spec:
  containers:
  - name: pod-configmap-volume-all-test
    image: "busybox"
    command: ['/bin/sh', '-c', 'sleep 3600']
    volumeMounts: # 在容器中声明挂载信息
    - name: app
      mountPath: /app
  volumes: # 指定挂载详情
  - name: app
    configMap: # 以configmap方式挂载,这只是其中一种,还可以是secret、cephfs、nfs、hostPath等
      name: my-config # configMap资源名称,下面不加items属性,这种会挂载所有文件(键为名,值为文件内容)到容器指定位置

进入busybox看一下效果吧,如下:

在这里插入图片描述

165.2.2.2、挂载ConfigMap中的部分键值

apiVersion: v1
kind: Pod
metadata:
  name: "pod-configmap-volume-items-test"
  namespace: default
  labels:
    app: "pod-configmap-volume-items-test"
spec:
  containers:
  - name: pod-configmap-volume-items-test
    image: "busybox"
    command: ['/bin/sh', '-c', 'sleep 3600']
    volumeMounts: # 在容器中声明挂载信息
    - name: app
      mountPath: /app # app会被当做目录
  volumes: # 指定挂载详情
  - name: app
    configMap: # 以configMap方式挂载,这只是其中一种,还可以是secret、cephfs、nfs、hostPath等
      name: my-config # configMap资源名称
      items:
      - key: username # configMap中的键名
        path: info/username.txt # 必须是相对路径,否则会报错
      - key: password # configMap中的键名
        path: info/password.txt # 必须是相对路径,否则会报错

进入busybox看一下效果吧,如下:

在这里插入图片描述

165.2.3、spec.containers.volumeMounts.subPath的使用

具体用法大家看一下就知道了,官方不建议使用subPath,原因是:

configMap、hostPath外边的内容更新的时候不会更新容器里面的内容,而不用subPath的情况会进行热更新

apiVersion: v1
kind: Pod
metadata:
  name: "pod-configmap-volume-items-test-2"
  namespace: default
  labels:
    app: "pod-configmap-volume-items-test-2"
spec:
  containers:
  - name: pod-configmap-volume-items-test-2
    image: "busybox"
    command: ['/bin/sh', '-c', 'sleep 3600']
    volumeMounts: # 在容器中声明挂载信息
    - name: username
      mountPath: /app/username.txt # 下面写subPath,这必须写上username.txt,不然app会被当成文件,然后把username.txt放在app文件中
      subPath: username.txt # 和上面的username.txt一致即可;可用于指定所引用的卷内的子路径,而不是其根路径。
  volumes: # 指定挂载详情
  - name: username
    configMap: # 以configMap方式挂载,这只是其中一种,还可以是secret、cephfs、nfs、hostPath等
      name: my-config # configMap资源名称
      items:
      - key: username # configMap中的键名
        path: username.txt # 必须是相对路径,否则会报错

165.3、公司使用configMap示例

先说一下configMap的创建结果:

在这里插入图片描述

在来看我们在项目的yaml文件中如何使用他们呢,如下:

在这里插入图片描述

以下截图是和上面containers同级的volumes的内容:

在这里插入图片描述

165.4、configMap和secret的区别

  • secret可以创建的种类多,而configMap可以创建的种类少:secret可以创建的种类分别有tls(创建一个 TLS secret;例如:ingress安全连接的密钥创建)、docker-registry(创建一个给 Docker registry 使用的 secret;例如连接阿里云私有镜像仓库的用户名和密码配置)、generic(从本地 file, directory 或者 literal value 创建一个 secret;这就是上面讲解的最常用的要求);而configMap只相当于拥有generic这一个
  • secret的内容是Base64加密存储的,而configMap中的内容是明文存储的
  • secret用的次数比较少,而configMap比较常用一点

166、k8s存储-卷挂载-hostPath、emptyDir方式_1

166.1、emptyDir

161.1.1、概念

  • emptyDir方式挂载的目录随Pod而生,随Pod而死,所以数据一般不妨在它里面
  • 卷最开始是空的
  • 存储空间来自于本地kubelet根目录(通常是根磁盘)或者内存,这个可以通过参数进行设置;其中pod.spec.volumes.emptyDir.medium默认值是空串,那么将存储在kubelet根目录中,而pod.spec.volumes.emptyDir.medium的值为Memory的时候,那就会把数据存储在内存中了
  • Pod中的所有容器都可以使用这个空目录,下面例子就是最好的证明

161.1.2、示例

下面的例子是113、k8s工作负载-Pod的多容器协同中的例子

apiVersion: v1
kind: Pod
metadata:
  name: "multi-container-pod"
  namespace: default
  labels:
    app: "multi-container-pod"
spec:
  containers:
  - name: nginx-container
    image: "nginx"
    volumeMounts:
    - name: common-vol
      mountPath: /usr/share/nginx/html
  - name: alpine-container
    image: "alpine"
    command: ["/bin/sh", "-c", "while true; do sleep 1; date > /app/index.html; done;"]
    volumeMounts:
    - name: common-vol
      mountPath: /app
  volumes:
    - name: common-vol
      emptyDir: {
    
    } # docker匿名挂载

166.2、hostPath

166.2.1、概念

作用: 将主机上的目录/文件挂载到容器内

如果主机上的目录/文件不存在,但是我们还想让它在挂载的时候自动生成,那就可以使用spec.volumes.name.hostPath.type属性,可用值列表如下:

在这里插入图片描述

详细信息请看:https://kubernetes.io/zh-cn/docs/concepts/storage/volumes/#hostpath

然后给个示例吧,如下:

在这里插入图片描述

166.2.1、示例

166.2.1.1、将主机时间文件挂载到容器内部

作用: 这样容器内部的时间就是正常的,这个很重要

apiVersion: v1
kind: Pod
metadata:
  name: "pod-hostpath-test"
  namespace: default
  labels:
    app: "pod-hostpath-test"
spec:
  containers:
  - name: pod-hostpath-test
    image: "busybox"
    command: ['sleep', '3600']
    volumeMounts:
    - name: localtime
      mountPath: /etc/localtime # 接收主机上的时间文件
  volumes:
    - name: localtime
      hostPath: # 将主机的时间文件挂载到容器内部
        path: /usr/share/zoneinfo/Asia/Shanghai

进入busybox容器查看结果,如下:

在这里插入图片描述

说明:虽然两个都是文件,但是依然挂载成功了

166.2.2、configMap和hostPath的区别

  • 相同
    • subPath使用之后,容器中的内容不会热更新
  • 不同
    • mountPath挂载方式不同:如果仅仅使用spec.containers.volumeMounts.mountPath,而不使用spec.containers.volumeMounts.subPathconfigMap会把该路径当做目录,然后把相关文件放在它下面;而hostPath会根据spec.volumes.hostPath.path的类型来决定spec.containers.volumeMounts.mountPath的类型,两者是相等的
    • subPath挂载方式不同:如果spec.containers.volumeMounts.mountPathspec.containers.volumeMounts.subPath都使用;configMap会把mountPath当成文件,hostPath的不咋会

167、k8s存储-nfs文件系统环境搭建_1

85、k8s-集群创建完成已经搭建完成了

168、k8s存储-nfs进行挂载_1

yaml文件直接就在下面,yaml文件的作用是把index.html文件放在nfs的共享目录中,我们直接通过修改nfs共享目录下test目录中的index.html,那就可以修改访问pod的返回结果

apiVersion: v1
kind: Pod
metadata:
  name: "pod-nginx-nfs-direct"
  namespace: default
  labels:
    app: "pod-nginx-nfs-direct"
spec:
  containers:
  - name: pod-nginx-nfs-direct
    image: "nginx"
    ports:
    - containerPort:  80
      name:  http
    volumeMounts:
    - name: localtime
      mountPath: /etc/localtime
    - name: html
      mountPath: /usr/share/nginx/html # 这也是已经存在的一个目录,用来存储访html文件,比如index.html
  volumes:
    - name: localtime
      hostPath:
        path: /usr/share/zoneinfo/Asia/Shanghai
    - name: html
      nfs: # 采用nfs方式进行挂载
        server: 192.168.139.133 # 这是nfs所在虚拟机的浏览器访问地址,不是nfs服务的内网地址
        path: /nfs/data/test # 这也是已经存在的一个目录,其中/nfs/data目录是nfs的存储目录,目前里面存放的是index.html

169、k8s存储-pv与pvc与Pod的使用_1

169.1、pv、pvc、storageClass

  • pv(PersistentVolume):真正落地存储,和物理存储目录关联,每一个pv都位于pv池中
  • pvc(PersistentVolumeClaim):申请pv的一个说明,里面需要写用什么存储类、容量大小、删除策略等信息
  • storageClass:这是存储类,相当于pv的一个分类,用来区分不同种类的pv,pv池中虽然含有很多pv,但是每一个pv都有不同的类别,比如存储类可以是我们自己命名的一个名称,或者是nfs的动态存储

在这里插入图片描述

169.2、手动创建PV,实现PVC静态供应

说明: 下面举例中静态供应使用的是nfs中的目录,其中静态供应中的目录没有任何的限制,只要是目录就是可以的

169.2.1、手动创建PV

下面创建了3个pv,分别是10m、100m、1g的pv,如下图所示:

在这里插入图片描述

创建10m的pv:

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-10m-test
  namespace: default
  labels:
    app: pv-10m-test
spec:
  storageClassName: my-self-storage # 存储类名称,每一个pod都隶属于一个存储类
  capacity:
    storage: 10m # 标明容量
  accessModes:
  - ReadWriteOnce # 访问模式
  nfs:
    server: 192.168.139.133 # nfs所在的虚拟机路径
    path: /nfs/data/a # /nfs/data是nfs的主目录,目录a是已经创建好的目录

创建100m的pv:

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-100m-test
  namespace: default
  labels:
    app: pv-100m-test
spec:
  storageClassName: my-self-storage # 存储类名称,每一个pod都隶属于一个存储类
  capacity:
    storage: 100m # 标明容量
  accessModes:
  - ReadWriteOnce # 访问模式
  nfs:
    server: 192.168.139.133 # nfs所在的虚拟机路径
    path: /nfs/data/b # /nfs/data是nfs的主目录,目录b是已经创建好的目录

创建1g的pv:

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-1gi-test
  namespace: default
  labels:
    app: pv-1gi-test
spec:
  storageClassName: my-self-storage # 存储类名称,每一个pod都隶属于一个存储类
  capacity:
    storage: 1Gi # 标明容量
  accessModes:
  - ReadWriteOnce # 访问模式
  nfs:
    server: 192.168.139.133 # nfs所在的虚拟机路径
    path: /nfs/data/c # /nfs/data是nfs的主目录,目录c是已经创建好的目录

169.2.2、手动创建PVC去申请PV

在下面的yaml文件中我们创建了一个20m的申请书,并且使用的存储类就是创建上面pv时用到的存储类,所以k8s会在该存储类下面的所有pv中选择一个容量最合适的pv,然后将该pv和pvc绑定,我们上面创建了10m、100m、1g的pv,那最合适的肯定是100m的pv了,所以pvc和100m的pv进行绑定,如下所示:

在这里插入图片描述

pvc本次在该存储类下面的pv列表中找到了合适的pv,如果找不到的话,那么pvc的状态会一直是pending

这种做法的坏处就是需要提前去创建PV,这样会增加运维工程师的工作量,所以最好是自动根据申请书的容量去创建PV,这样既可以减轻运维工程师的工作量,还可以按需获取PV,不会浪费存储空间,后续我们会说到nfs动态挂载,它的出现就是为了解决上述两个问题的

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-20m-test
  namespace: default
  labels:
    app: pvc-20m-test
spec:
  storageClassName: my-self-storage # 说明使用那个存储类,只能使用该存储类下的pv
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 20m # 说明pvc申请书的容量

169.3、创建Pod去使用PVC

上面已经创建了pvc,并且pvc已经和pv进行了绑定,下面这个yaml文件的作用就是使用这个pvc,我们此处看一下pod的状态,如下:

在这里插入图片描述

然后我们创建一个index.html放在pv里面,并且修改index.html的内容,直接访问pod的ip,发现输出的正是index.html中的内容,如下:

在这里插入图片描述
yaml文件如下:

apiVersion: v1
kind: Pod
metadata:
  name: "pod-nginx-static-pvc-test"
  namespace: default
  labels:
    app: "pod-nginx-static-pvc-test"
spec:
  containers:
  - name: pod-nginx-static-pvc-test
    image: "nginx"
    ports:
    - containerPort:  80
      name:  http
    volumeMounts:
    - name: localtime
      mountPath: /etc/localtime
    - name: html
      mountPath: /usr/share/nginx/html # 这也是已经存在的一个目录
  volumes:
    - name: localtime
      hostPath:
        path: /usr/share/zoneinfo/Asia/Shanghai
    - name: html
      persistentVolumeClaim: # 使用存储卷声明方式
        claimName: pvc-20m-test # pvc名称

170、k8s存储-pv的回收策略等细节

170.1、回收策略类型

  • Retain:默认值,即使删除了pvc,pvc对应的目录也不会删除,里面的内容更不会删除,并且pv的状态就从Bound变成Released,虽然看起来是释放了,但是以后不能被任何PVC绑定,即使是原来的PVC也不行,这个我已经尝试过了
  • Recycle:即使删除了pvc,pvc对应的目录也不会删除,但是目录里面的东西会自动删除,并且PV的type从Bound变成Available,那以后就可以被其他PVC挂载,NFS和HostPath支持该用法
  • Delete:诸如AWS EBS、GCE PD、Azure Disk或OpenStack Cinder卷这类的关联资产也会被删除;
    • 如果静态供应中的NFS使用这种方案,当删除PVC之后,PV的type从Bound变成Failed,说明回收失败了,pv对应目录以及目录中的内容也不会被删除,但是以后不能被任何PVC绑定,即使是原来的PVC也不行,这个我已经尝试过了
    • 如果动态供应中的NFS使用这种方案,那是可以奏效的,并且可以通过设置注解来完成删除pv之前将pv备份的功能,然后在删除pv,这一点在创建动态供应nfs的时候已经设置过了,如下图所:
      在这里插入图片描述

拓展:

既然提到了pv中的type,那我们再说一下pvc中的type,其中pvc中type的默认值是Delete,另外两种是Retain、Recycle,所以pvc中的type和pv中的一样,对于NFS动态供应来说,我们直接通过NFS动态供应的存储类创建的pv的type和pvc的type一致

如果使用85、k8s-集群创建完成中搭建的那一套NFS动态供应,并且创建存储类的时候设置了自动删除备份功能,也就是上图红色框中框选的部分,那我们删除pvc的时候也会同步删除pv,并且在删除pv之前将pv的内容部分好,备份文件夹名称是archived-名称空间-pvc名称-pv名称,例如:archived-test-image-pvc-5eb7d15c-c81e-4074-803b-2c691542a37a

170.2、PV、PVC如何设置回收策略

PV:

在这里插入图片描述

PVC:

在这里插入图片描述

170.3、Pod、PVC、PV删除所产生的影响

  • Pod:Pod删除不会删除PVC
  • PVC:Pod没有删除的时候pvc不能删除,PVC删除之后会对PV产生影响
  • PV:PV删除的时候可能会备份,其中NFS动态供应中在存储类中设置相关注解才行,如下:
    在这里插入图片描述

171、k8s存储-动态供应原理与流程_1

171.1、PV和PVC访问模式

下面这几种访问模式,PV和PVC都是支持的,如果是静态供应的情况,我们需要手动设置PV的访问模式;如果是NFS动态供应的话,我们只需要设置PVC的访问模式,然后就可以间接设置PV的访问模式

  • ReadWriteOnce:卷可以被一个节点以读写方式挂载。 ReadWriteOnce 访问模式也允许运行在同一节点上的多个 Pod 访问卷。
  • ReadOnlyMany:卷可以被多个节点以只读方式挂载。
  • ReadWriteMany:卷可以被多个节点以读写方式挂载。

上述3种方式,NFS都是支持的

PV示例如下:

在这里插入图片描述

PVC示例如下:

在这里插入图片描述

171.2、动态供应图

在这里插入图片描述

换一种表示方式:

在这里插入图片描述

172、k8s存储-动态供应完成_1

说明: 85、k8s-集群创建完成已经讲过了

172.1、使用NFS动态供应创建PVC

下面这个例子就是PVC使用NFS动态供应的例子

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nginx-pvc-2
  namespace: default
  labels:
    app: nginx-pvc-2
spec:
  storageClassName: managed-nfs-storage  ## NFS动态供应的存储类名字,按照你自己的填写,如果设置了默认存储类,就可以不设置该值,默认也会使用默认存储类
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 100m

猜你喜欢

转载自blog.csdn.net/qq_42449963/article/details/129105804