1.内容介绍

1. 服务发现及负载均衡型资源(Service);(掌握)
2. 存储型资源-存储卷;(掌握)
3. 存储型资源-特殊存储卷(ConfigMap,SerivceAcout);(掌握)
4. 和Springcloud集成;(了解)

2.服务发现及负载均衡型资源(Service)

我们知道pod的ip不是固定的,是根据所在宿主机的docker0网卡生成的,每次重启,更新,调度等情况IP都会变,那pod与pod之间需要互相调用,肯定不能用ip的,因为地址不是固定的, 如何能保障pod之前访问的可靠性,由此就衍生出Service的概念

Service是Pod上的资源抽像,将标签选择器选定的一组Pod定义统一固定访问入口(IP及DNS名称),到达Service的请求将负载均衡到后端的各Pod。 Service也可将集群外部流量引入到集群中

2.1.概念

service是kubernetes中最核心的资源对象之一,service和pod之间是通过Label串起来,相同的Service的pod的Label是一样的.同一个service下的所有pod是通过kube-proxy实现负载均衡.而每个service都会分配一个全局唯一的虚拟ip,也就cluster ip.
在该service整个生命周期内,cluster ip保持不变,而在kubernetes中还有一个dns服务,它会把service的name解析为cluster ip.
在这里插入图片描述
Service是一组pod的统一访问入口(ip,域名-ip),客户端通过ip或域名访问Service会实现负载均衡调用。

2.2.Service工作模式

Kubernetes 集群中,每个 Node 运行一个 kube-proxy 进程。kube-proxy 负责为 Service 实现了一种 VIP(虚拟 IP)的形式。 在 Kubernetes v1.0 版本,代理完全在 userspace。在 Kubernetes v1.1 版本,新增了 iptables 代理,但并不是默认的运行模式。 从 Kubernetes v1.2 起,默认就是 iptables 代理。在Kubernetes v1.8.0-beta.0中,添加了ipvs代理。

在 Kubernetes v1.0 版本,Service 是 “4层”(TCP/UDP over IP)概念。 在 Kubernetes v1.1 版本,新增了 Ingress API(beta 版),用来表示 “7层”(HTTP)服务。

kube-proxy 这个组件始终监视着apiserver中有关service的变动信息,获取任何一个与service资源相关的变动状态,通过watch监视,一旦有service资源相关的变动和创建,kube-proxy都要转换为当前节点上的能够实现资源调度规则(例如:iptables、ipvs)

在这里插入图片描述

2.2.1 userspace代理模式

这种模式,当客户端Pod请求内核空间的service iptables后,把请求转到给用户空间监听的kube-proxy 的端口,由kube-proxy来处理后,再由kube-proxy将请求转给内核空间的 service ip,再由service iptalbes根据请求转给各节点中的的service pod。

由此可见这个模式有很大的问题,由客户端请求先进入内核空间的,又进去用户空间访问kube-proxy,由kube-proxy封装完成后再进去内核空间的iptables,再根据iptables的规则分发给各节点的用户空间的pod。这样流量从用户空间进出内核带来的性能损耗是不可接受的。在Kubernetes 1.1版本之前,userspace是默认的代理模型。

在这里插入图片描述
请求流程:Client Pod -> Service IP -> kube-proxy -> Service IP -> ServerPod 2
缺点:请求流程复杂,性能差

2.2.2 iptables代理模式

客户端IP请求时,直接请求本地内核service ip,根据iptables的规则直接将请求转发到到各pod上,因为使用iptable NAT来完成转发,也存在不可忽视的性能损耗。另外,如果集群中存在上万的Service/Endpoint,那么Node上的iptables rules将会非常庞大,性能还会再打折扣。iptables代理模式由Kubernetes 1.1版本引入,自1.2版本开始成为默认类型。
在这里插入图片描述
请求流程:Client Pod -> Service IP(iptables) -> Server Pod
缺点:如果集群中的节点比较多,那么Service IP的压力会特别大

2.2.3 ipvs代理模式
Kubernetes自1.9-alpha版本引入了ipvs代理模式,自1.11版本开始成为默认设置。
客户端IP请求时到达内核空间时,根据ipvs的规则直接分发到各pod上。
kube-proxy会监视Kubernetes `Service`对象和`Endpoints`,
调用`netlink`接口以相应地创建ipvs规则并定期与Kubernetes `Service`对象和`Endpoints`对象同步ipvs规则,以确保ipvs状态与期望一致。
访问服务时,流量将被重定向到其中一个后端Pod。

与iptables类似,ipvs基于netfilter 的 hook 功能,
但使用哈希表作为底层数据结构并在内核空间中工作。
这意味着ipvs可以更快地重定向流量,并且在同步代理规则时具有更好的性能。
此外,ipvs为负载均衡算法提供了更多选项,例如:

rr:`轮询调度` 
lc:最小连接数 
`dh`:目标哈希
`sh`:源哈希
`sed`:最短期望延迟
`nq`:不排队调度

注意: ipvs模式假定在运行kube-proxy之前在节点上都已经安装了IPVS内核模块。
当kube-proxy以ipvs代理模式启动时,kube-proxy将验证节点上是否安装了IPVS模块,
如果未安装,则kube-proxy将回退到iptables代理模式。

在这里插入图片描述

如果某个服务后端pod发生变化,标签选择器适应的pod有多一个,适应的信息会立即反映到apiserver上,
而kube-proxy一定可以watch到etc中的信息变化,而将它立即转为ipvs或者iptables中的规则,
这一切都是动态和实时的,删除一个pod也是同样的原理。如图:

在这里插入图片描述

2.3.服务暴露-pod暴露
2.3.1.服务暴露四种方式

服务暴露,也称为发布服务到外部网络中

Service类型

共四种类型:ClusterIP、NodePort、LoadBalancer、ExternalName

  • ClusterIP,默认,仅集群内可达(集群内部,Node之间访问):比如Redis就用它,zuul不能用它
  • NodePort,构建在ClusterIP之上,在每个机器上绑定一个端口<NodeIP>:<NodePort>进行请求,默认端口范围 30000~3276 , 比如一个nginx应用需要能被外部访问,就需要配置类型为type=NodePort,并且需要配置下nodePort: 30002(指定 固定端口),这样的话外部使用http://node机器IP:30002就可以访问这个应用了
  • LoadBalancer,构建在NodePort之上,使用运营商负载均衡器(互联网访问,需要购买负载均衡器)
  • ExternalName,用于将外部服务映射到集群内,让集群内Pod资源能够访问,故其没有ClusterIP、NodePort、标签选择器和Endpoints
2.3.2.ClusterIP

使用ClusterIP的方式负载均衡多个pod ,默认,仅集群内可达

1.创建资源文件:

vim test-service1.yaml   内容如下:
apiVersion: v1
kind: Service #资源类型 Service
metadata:
  name: myservice1
spec:
  type: ClusterIP #服务暴露方式
  selector:
      app: deploy-demo #pod的label标签名,可以使用  kubectl get pod --show-labels 查看pod的 label
  ports:
    - name: http
      port: 8080 #映射的端口
      targetPort: 8080 #pod内部端口

命令提示:可以使用 kubectl get pod --show-labels 查看pod的 label

2.应用资源文件
kubectl apply -f test-service1.yaml
在这里插入图片描述
3.查看service选择的pod
Ipvsadm
在这里插入图片描述
注意:如果修改了pod的label就匹配不到了

Headless Service

如果我们不需要做负载均衡,也不需要指定ClusterIP,那我们可以吧ClusterIp的值指定为“None”,即Headless Server ,这种模式不会被分配Cluster IP, kube-proxy也不会去代理他们,平台也不会为他们进行负载均衡

有时候我们创建的服务不想走负载均衡,想直接通过pod-ip链接后端,怎么办呢,使用headless service接可以解决。headless service 是将service的发布文件中的clusterip=none ,不让其获取clusterip , DNS解析的时候直接走pod。

1.创建资源文件

vim test-service2.yaml
apiVersion: v1
kind: Service
metadata:
  name: myservice-headless
spec:
  type: ClusterIP
  clusterIP: "None" #不要iP
  selector:
      app: deploy-demo
  ports:
    - name: http
      port: 8080  
      targetPort: 8080

2.申请资源文件

kubectl apply -f test-service2.yaml

3.查看服务
kubectl get svc
在这里插入图片描述
没有ip通过域名访问,选一个coredns来解析试一下

4.查看系统自带的域名解析服务
kubectl get pod -n kube-system -o wide
在这里插入图片描述

5.执行解析

dig -t A myservice-headless.default.svc.cluster.local. @192.168.249.79

解释:这里的 myservice-headless 对应了资源文件中的 metadata.name 资源名字 ,
default.svc.cluster.local. 是固定内容 , @192.168.32.171 是coredns域名解析服务的IP
在这里插入图片描述

6.使用域名访问

curl myservice-headless.default.svc.cluster.local.:8080
2.3.3.NodePort

构建在ClusterIP之上做端口绑定,增加:进行请求,默认端口范围 30000~32767

1.创建资源文件

vim test-service3.yaml

2.拷贝内容如下

apiVersion: v1
kind: Service
metadata:
  name: myservice-nodeport
spec:
  type: NodePort
  selector:
      app: deploy-demo
  ports:
    - name: http
      port: 8080  
      targetPort: 8080

网络模式为:NodePort ,将8080端口映射给pod内部的8080端口

3.应用资源文件

kubectl apply -f  test-service3.yaml

4.查看服务
kubectl get svc
在这里插入图片描述
解释:这里的ClusterIP 为 10.106.136.213 ,将容器内部端口 8080映射给集群外部的端口为 308141

我们可以使用“http://10.106.136.213:8080/”在集群内部访问,由于这个地址映射给308141,如果我当前服务器的ip为192.168.0.113 ,那么我可以在集群外部使用:http://192.168.0.115:30841/去访问

通过:http://192.168.0.115:30841?t=1 ; http://192.168.0.115:30841?t=2 切换不同的实例

2.3.4.LoadBalancer

LoadBalancer,构建在NodePort之上,使用运营商负载均衡器

2.3.5.ExternalName

将Service映射至由externalName指定的主机名来暴露服务,此主机名需要被DNS解析到 CNAME类型的记录

2.4.Ingress负载均衡器
2.4.1.理解Ingress

Service 暴露给外界的三种方法(NodePort,LoadBalancer,ExternalName )。其中有一个叫作LoadBalancer 类型的 Service,它会为你在 Cloud Provider(比如:Google Cloud 或者OpenStack)里创建一个与该 Service 对应的负载均衡服务。

但是,相信你也应该能感受到,由于每个 Service 都要有一个负载均衡服务,所以这个做法实际上既浪费成本又高。作为用户,我其实更希望看到 Kubernetes 为我内置一个全局的负载均衡器。然后,通过我访问的 URL,把请求转发给不同的后端 Service。

这种全局的、为了代理不同后端 Service 而设置的负载均衡服务,就是Kubernetes 里的Ingress 服务。所以,Ingress 的功能其实很容易理解:所谓 Ingress,就是 Service 的“Service”。
在这里插入图片描述

Ingress:
 Ingress是HTTP(S)负载均衡器,应用层调度,支持多种后端健康状态检查而Service是TCP负载均衡器,传输层调度,不支持健康检查
 Ingress是一组基于DNS名称或URL路径把请求转发到指定Service资源(或Pod资源)的规则,用于集群内部服务发布。
 当Ingress绕过Service直接到具体Pod时,可节省由kube-proxy的代理开销

Ingress Controller:
 Ingress资源需要通过Ingress Controller实现功能
 Ingress由任何具有反向代理功能的程序实现,如Nginx、Envoy、HAProxy、Vulcand、Traefik等,Ingress本身是运行于集群中的Pod资源对象
在这里插入图片描述

2.4.2.Ingress实战

案例分析:
在这里插入图片描述
官网:https://github.com/kubernetes/ingress-nginx/tree/nginx-0.30.0/deploy
在三个节点导入镜像 nginx-ingress-controller.tar

注意:ingress controller本身是一个Pod,内部运行了一个Nginx容器,同时也创建了deployment去管理Pod,同时需要创建了Service去暴露服务。

1.上传镜像和资源

上传 nginx-ingress-controller.tar 到主节点,然后使用命令拷贝到其他机器上

scp -r nginx-ingress-controller.tar root@192.168.0.114:/root/

2.加载镜像(3台)

docker load -i nginx-ingress-controller.tar

3.创建nginx-ingress-controller

vi mandatorynew.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: quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.26.1
          imagePullPolicy: Never
          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 -> 33
            runAsUser: 33
          env:
            - name: POD_NAME
              valueFrom:
                fieldRef:
                  fieldPath: metadata.name
            - name: POD_NAMESPACE
              valueFrom:
                fieldRef:
                  fieldPath: metadata.namespace
          ports:
            - name: http
              containerPort: 80
            - name: https
              containerPort: 443
          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

---
kubectl apply -f mandatorynew.yaml  应用资源
kubectl get pods -n ingress-nginx   查看pos

mandatorynew.yaml是官方提供的安装ingress的资源文件

5.暴露nginx-ingress-controller

vi service-nodeport.yaml
apiVersion: v1
kind: Service
metadata:
  name: ingress-nginx
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
spec:
  type: NodePort
  ports:
    - name: http
      port: 80
      targetPort: 80
      protocol: TCP
    - name: https
      port: 443
      targetPort: 443
      protocol: TCP
  selector:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx

---
kubectl apply -f service-nodeport.yaml

暴露nginx-ingress-controller给外部访问

查看服务

kubectl get pods -n ingress-nginx
kubectl get deployment -n ingress-nginx
kubectl get rs -n ingress-nginx
kubectl get svc -n ingress-nginx

6.创建2个Deployment(创建2pod)和service进行测试

vi ingresshttp.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: ingresshttp-dep
spec:
  replicas: 2
  selector:
    matchLabels:
      app: ingresshttp-myapp
  template:
    metadata:
      labels:
        app: ingresshttp-myapp
    spec:
      containers:
      - name: myapp
        image: tomcat:v1
        imagePullPolicy: Never
        ports:
        - name: http
          containerPort: 8080
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: ingresshttp-dep1
spec:
  replicas: 2
  selector:
    matchLabels:
      app: ingresshttp-myapp1
  template:
    metadata:
      labels:
        app: ingresshttp-myapp1
    spec:
      containers:
      - name: myapp
        image: tomcat:v2
        imagePullPolicy: Never
        ports:
        - name: http
          containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: ingresshttp-svc
spec:
  type: ClusterIP
  selector:
      app: ingresshttp-myapp
  ports:
    - name: http
      port: 8080
      targetPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: ingresshttp-svc1
spec:
  type: ClusterIP
  selector:
      app: ingresshttp-myapp1
  ports:
    - name: http
      port: 8080
      targetPort: 8080
kubectl apply -f ingresshttp.yaml

查看service

kubectl get svc

7.配置ingress

vi  ingress.yml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: httpingress
spec: 
  rules:
    - host: www.hrm.com
      http: 
        paths: 
          - path: /
            backend: 
              serviceName: ingresshttp-svc
              servicePort: 8080
    - host: course.hrm.com
      http: 
        paths: 
          - path: /
            backend: 
              serviceName: ingresshttp-svc1
              servicePort: 8080               
kubectl apply -f ingress.yml

查看ingress

kubectl get ingress

8.windows配置hosts

192.168.0.113 www.hrm.com
192.168.0.113 course.hrm.com

9.浏览器访问
http://www.hrm.com:31193/

这里的端口是 Ingress暴露的端口可以通过 kubectl get svc -n ingress-nginx 查看
在这里插入图片描述
在这里插入图片描述
进入容器查看Nginx配置:

kubectl exec -it nginx-ingress-controller-599f95f447-kngrr -c nginx-ingress-controller -n ingress-nginx -- /bin/bash
cat /etc/nginx/nginx.conf 
2.5.服务发现-Service Discovery

什么是服务发现:

服务发现在微服务架构里,服务之间经常进行通信,服务发现就是解决不同服务之间通信的问题。比如一个nginx的pod,要访问一个mysql服务,就需要知道mysql服务的ip和port,获取ip和port的过程就是服务发现。
在这里插入图片描述
kubernetes 支持两种服务发现模式CoreDNS 和环境变量

2.5.1 服务发现方式:环境变量

当Pod被创建的时候,k8s将为Pod设置每一个Service的相关环境变量,比如PodA要找到PodB,PodA需要通过环境变量找到service,然后在找到PodB

k8s为Service设置的环境变量形式,包括:

{SVCNAME}_SERVICE_HOST
{SVCNAME}_SERVICE_PORT
{SVCNAME}_SERVICE_PORT_{PORTNAME}

其中的服务名和端口名转为大写,连字符转换为下划线。

vim test-pod.yaml

docker pull busybox
apiVersion: v1
kind: Pod
metadata:
  name: test-api
spec:
  containers:
    - name: test-api
      image: busybox
      imagePullPolicy: Never
      command: ["/bin/sh", "-c", "env"] #打印环境变量

kubectl apply -f test-pod.yaml

解释:busybox可以看做是一个迷你版本的linux
在这里插入图片描述

查看日志:

kubectl logs test-api | grep INGRESSHTTP_SVC

在这里插入图片描述

可以直接通过 NGINX.SERVICESERVICE.HOST 和 NGINX.SERVICESERVICE.PORT ,这样也是一种方式。如果存在依赖关系可以通过初始化容器的方式,但是这种方式有点复杂,每次编写yaml的,真不具有通用性,不是最优解啊。

Docker Link环境变量:相当于通过 Docker 的–link 参数实现容器连接时设置的环境变量形式;

2.5.2 服务发现方式:DNS

DNS服务发现需要k8s提供 Cluster DNS支持,Cluster DNS会监控k8s API,为每一个Service创建DNS记录用于域名解析,这样在Pod中可以通过DNS域名获取Service的访问地址。而对于一个Service, Cluster DNS会创建两条DNS记录:

[service_name].[namespace_name].[cluster_domain]

[service_name].[namespace_name].svc.[cluster_domain]

① DNS发展史
在这里插入图片描述
在这里插入图片描述
②coreDNS
实现的功能和 KubeDNS 是一致的,不过 CoreDNS 的所有功能都集成在了同一个容器中,在最新版的1.11.0版本中官方已经推荐使用 CoreDNS了,大家也可以安装 CoreDNS 来代替 KubeDNS,其他使用方法都是一致的:https://coredns.io/
在这里插入图片描述
③查看
在这里插入图片描述
④域名格式

1.普通的 Service
会生成 servicename.namespace.svc.cluster.local 的域名,会解析到 Service 对应的 ClusterIP 上,在 Pod 之间的调用可以简写成 servicename.namespace,如果处于同一个命名空间下面,甚至可以只写成 servicename 即可访问

2.Headless Service
无头服务,就是把 clusterIP 设置为 None 的,会被解析为指定 Pod 的 IP 列表,同样还可以通过 podname.servicename.namespace.svc.cluster.local访问到具体的某一个 Pod。
在这里插入图片描述
域名解析
在这里插入图片描述

dig -t A ingresshttp-svc.default.svc.cluster.local @192.168.16.130
dig -t A 解析的服务名.命名空间.svc.cluster.local @coreDns的ip

corends运行不成功解决办法:
https://blog.csdn.net/qq_40806970/article/details/99845808?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param

3.存储型资源-存储卷

3.1.存储卷类型
K8s支持非常多的存储卷类型:本地存储、网络存储系统、Secret、ConfigMap都属于存储资源

本地存储:
emptyDir和hostPath属于节点级别的卷类型(针对当前机器),不具有持久性 emptyDir生命周期与Pod相同;
使用hostPath的Pod一但重被调度至其他节点,将无法使用之前的数据

网络存储系统:
集群级别资源PersistentVolume,PV,由管理员配置存储系统;用户通过persistentVolumeClaim,PVC,申请使用,简化终端存储用户配置过程

Secret用于传递敏感信息;
ConfigMap用于向Pod注入非敏感数据

常用分类: 
	emptyDir(临时目录):Pod删除,数据也会被清除,这种存储成为emptyDir,用于数据的临时存储。 
	hostPath(宿主机目录映射): 
	本地的SAN(iSCSI,FC)、
	NAS(nfs,cifs,http)存储 
	分布式存储(glusterfs,rbd,cephfs) 
	云存储(EBS,Azure Disk)
3.2.存储卷使用方式

在pods.spec.volumes中定义需要使用的卷列表,在pods.containers.volumeMounts中进行挂载(可不挂载任何存储卷) 多个容器可挂载同一个存储卷,此时即为共享目录 挂载相关参数: name,必须,指定要挂载的存储的名称 mountPath,必须,挂载点 readOnly,boolean,是否挂载为只读 subPath,使用子路径挂载,即在mountPath指定路径的子路径作为挂载点

3.3.节点级存储卷

emptyDir 生命周期与Pod相同,不能提供持久化存储能力 主要讲这个 gitRepo 基于emptyDir构建,从Git仓库中复制相应数据到底层emptyDir中

3.3.1 emptyDir 临时存储卷

在Pod启动时被创建,在Pod移除时一并删除 spec.volumes.emptyDir.medium,存储介质类型,default 或 Memory spec.volumes.emptyDir.sizeLimit,空间限额,默认为nil 注间,在类型为Memory时,一定要定义限额

我们来演示一个案例,一个Pod中的2个容器使用存储卷实现数据的共享, 这里会创建一个Tomcat的容器和一个busybox的容器,他们两个容器共享一个数据卷,当我们修改busybox中的数据卷目录中的内容时,Tomcat中的数据卷目录中的内容也会跟着变。

1.创建资源文件

vim em.yaml

2.增加如下内容

apiVersion: v1
kind: Pod
metadata:
  name: vol-emptydir-pod
spec:
  volumes: #存储卷
    - name: appvol
      emptyDir: {} #类型为emptyDir
  containers:
    - name: myappv1
      image: tomcat:v1
      ports:
        - name: http
          containerPort: 8080
      volumeMounts:
        - name: appvol
          mountPath: '/usr/local/tomcat/webapps/ROOT'
    - name: busybox    
      image: busybox
      imagePullPolicy: IfNotPresent
      command: ['sh', '-c', 'sleep 3600']
      volumeMounts:
        - name: appvol
          mountPath: '/usr/local/myapp'

两个容器的存储卷共享

3.应用资源文件

kubectl apply -f em.yaml
  1. 查看pod
kubectl get pod

curl 192.168.249.86:8080 访问容器

4.进入Tomcat容器,增加html页面

kubectl exec vol-emptydir-pod -c myappv1 -it -- /bin/sh

5.在ROOT增加html

cd /usr/local/tomcat/webapps/ROOT 
echo index > index.html
exit

使用url访问该pod就可以看到页面内容

6.进入busybox容器,增加页面

kubectl exec vol-emptydir-pod -c busybox -it -- /bin/sh
cd /usr/local/myapp  进入数据卷目录
echo  whale.chen to here >> index.html
exit

7.使用curl访问容器

curl 192.168.249.86:8080

看到的内容应该是有所变化,这里我们把容器 “myappv1”的 '/usr/local/tomcat/webapps/ROOT’目录 和 容器“busybox”的 '/usr/local/myapp’目录进行映射,当我们修改了busybox中的index.html内容,在myappv1中的index.html内容也会跟着改变,这个就是 emptyDir,实现同一个POD中的多个容器数据卷共享
两个容器都挂载了空加载卷,达到共享目录的效果
在这里插入图片描述

3.3.2 hostPath存储卷

使用节点上的目录或文件,具有持久性。尤适用于运行有管理任务的系统级Pod资源需要访问节点上的文件

spec.volumes.hostPath.path,必须,节点上的路径 spec.volumes.hostPath.type,存储卷类型,支持以下的值: - DirectoryOrCreate,指定的路径不存在时自动创建,权限为0755,属主为kubelet - Directory,必须存在的目录 - FileOrCreate,不存在时将自动创建的文件,权限为0644,属主为kubelet - File,必须存在的文件路径 - Socket,必须存在的Socket文件路径 - CharDevice,必须存在的字符设备文件路径 - BlockDevice,必须存在的块设备文件路径 注意: 1、不同节点上的文件可能存在差异,对于要求事先必须存在的文件或目录,可能会出现不满足的情形 2、基于资源可用状态调度Pod时,hostPath的可用性不会被考虑 3、节点中创建的文件或目录默认仅root可写,若要在容器内也可写,须将容器运行为特权容器,或修改节点上目录的权限

1.创建资源文件

vi hostpath.yml

2.加入内容

apiVersion: v1
kind: Pod
metadata:
  name: pod-vol-hostpath
  namespace: default
spec:
  containers:
  - name: myapp
    image: tomcat:v1
    volumeMounts:
    - name: html
      mountPath: /usr/local/tomcat/webapps/ROOT
  volumes:
  - name: html
    hostPath: #在当前pod所在机器上创建一个 /data/pod/volume1作为数据卷目录,映射到/usr/share/nginx/html
      path: /data/pod/volume1
      type: DirectoryOrCreate     #如果目录不存在就创建

3.应用资源文件

kubectl apply -f hostpath.yml

4.查看pod在哪个节点
kubectl get pod -o wide
在这里插入图片描述

5.在pod所在节点的数据卷目录增加index.html

切到node02所在的机器
cd /data/pod/volume1   进入数据卷目录
echo index > index.html  增加内容

在这里插入图片描述

6.回到master节点,访问pod

kubectl get pod -o wide
curl 192.168.32.182:8080

在这里插入图片描述
注意:这种方式,Node挂了,数据卷就会丢失 , 要解决这个问题就要使用集群级别的存储卷方式

3.4.集群级别存储卷

跳出节点的存储位置

  传统意义上的存储设备: 本地的SAN(iSCSI,FC)、NAS(nfs,cifs,http)存储
  分布式存储(glusterfs,rbd,cephfs)
  云存储(EBS,Azure Disk)

以下我们也nfs为例进行讲解,并且具体使用方式包括,直接连接,也可以使用PV和PVC来操作。所以接下来我们首先搭建一个nfs,并且分别也两种方式镜像搭建。

3.4.1 搭建Nfs
3.4.1.1 NFS服务端

选择另外一个服务器(云服务器)

#安装
yum install -y nfs-utils rpcbind
#检测是否安装成功
rpm -qa nfs-utils rpcbind
# 创建共享目录
mkdir -p /data/nfs1
#创建NFS配置文件
vi /etc/exports  内容如下:
/data/nfs1      *(insecure,rw,no_root_squash,no_all_squash,sync)

#要共享的目录      允许访问的网段(可以是一个IP地址或者主机名) rw是指可读可写
# 启动服务
systemctl start rpcbind.service && systemctl start nfs.service && systemctl enable rpcbind.service && systemctl enable nfs-server
#测试共享是否成功
showmount -e 118.25.154.214
3.4.1.2 NFS客户端

注意:所有节点都要安装

#安装
yum install -y nfs-utils rpcbind
#挂载
mkdir /root/nfsdata
mount 118.25.154.214:/data/nfs1 /root/nfsdata

在这里插入图片描述

mount | grep /root/nfsdata   检查是否挂载成功
# 卸载挂载
umount /root/nfsdata

NFS挂载时出现"access denied by server while mounting"的解决方法
http://www.hmjblog.com/system/linux/2998.html

测试:在任何一个Node的挂在目录这增加文件,其他的Node的挂载目录也会同步该文件。

cd /root/nfsdata
echo test > test.txt
切到另个Node上
ls /root/nfsdata
3.4.2 Pod使用Nfs数据卷

创建pod的时候,把mountPath挂在到当前node的数据卷挂载目录即可
1.创建资源

vi pod-nfs.yml

2.创建容器,挂在nfs数据卷目录

apiVersion: v1
kind: Pod
metadata:
  name: pod-vol-hostpath1
  namespace: default
spec:
  containers:
  - name: myapp1
    image: tomcat:v1
    volumeMounts:
    - name: html
      mountPath: /usr/local/tomcat/webapps/ROOT
  volumes:
  - name: html
    hostPath: #在当前pod所在机器上创建一个 /data/pod/volume1作为数据卷目录,映射到/usr/share/nginx/html
      path: /root/nfsdata
      type: DirectoryOrCreate     #如果目录不存在就创建

3.应用资源文件

kubectl apply -f pod-nfs.yml

4.查看pods

kubectl get pods -o wide
curl 192.168.249.88:8080

5.给数据卷目录添加页面

cd /root/nfsdata/
echo indexaaaaaaa > index.html

6.再次访问pods

curl 192.168.249.88:8080

这里看到的内容应该就是第 5 步骤的 index.html的内容

3.4.3 PV&PVC方式
3.4.3.1 概念理解

直接使用自助式pod直接连接存储的方式与kubernetes向用户和开发隐藏底层架构的目标相背离;对此,kubernetes使用PersistentVolume(简称PV)子系统在系统和管理员之间添加一个自系统,解决了这种问题。PV是集群级别的资源,不属于任何命名空间。

为了提供差异化的PV,引入新的资源对象 StorageClass ,用于将存储资源定义为具有显著特性的类别,而不是具体的PV,用户通过PersistentVolumeClaim(PVC)直接向意向类别发出申请,匹配由管理员事先创建的PV,或由其按需为用户动态创建PV,PV对存储系统的支持通过插件来实现创建的PV不会验证可用性,即可直接创建。

简单理解:使用Pod直接连接存储比较麻烦,我们可以使用PV来解决,创建好PV之后,我们的Pod直接使用PV就可以达到存储效果,PV可以支持多种类型的存储资源。
在这里插入图片描述
在这里插入图片描述

PV访问模式:
PersistentVolume 可以以资源提供者支持的任何方式挂载到主机上。如下表所示,供应商具有不同的功能,每个pv的访问模式都将被设置为该卷支持的特定模式。例如,NFS可以支持多个读/写客户端,但特定的NFS PV可能以只读方式导出到服务器上。每个PV都有一套自己的用来描述特定功能的访问模式
1 ReadWriteOnce- - 该卷可以被单个节点以读/写模式挂载
2 ReadOnlyMany-- -该卷可以被多个节 点以只读模式挂载
3 ReadWriteMany- -该卷可以被多个节点以读/写模式挂载
在命令行中,访问模式缩写为:
● RWO - ReadWriteOnce
● ROX- ReadOnlyMany
● RWX- ReadWriteMany

PV状态:
卷可以处于以下的某种状态:
● Available (可用) —块空闲资源还没有被任何声明绑定
● Bound (已绑定) – 卷已经被声明绑定
● Released (已释放) – 声明被删除,但是资源还未被集群重新声明
● Failed (失败) - - 该卷的自动回收失败

PV回收策略:
● Retain (保留) --管理员手动回收:kubectl delete pv pv-name 创建:kubectl apply -f pv-name.yaml ;Retain策略 在删除pvc后PV变为Released不可用状态, 若想重新被使用,需要管理员删除pv,重新创建pv,删除pv并不会删除存储的资源,只是删除pv对象而已;若想保留数据,请使用该Retain,
● Recycle (回收) - -删除pvc自动清除PV中的数据,效果相当于执行 rm -rf /thevolume/*. 删除pvc时.pv的状态由Bound变为Available.此时可重新被pvc申请绑定
● Delete (默认,删除) - -关联的存储资产(例如AWS EBS. GCE PD、Azure Disk和OpenStack Cinder卷)将被删除。

只有NFS和HostPath支持回收策略。AWS EBS、 GCE PD. Azure Disk和Cinder卷支持删除策略

3.4.3.2 创建PV

1.创建资源文件

vim pv.yaml

2.加入内容,创建4个PV

apiVersion: v1
kind: PersistentVolume #创建PV
metadata:
  name: nfspv1 #PV的名字
spec:
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteOnce #访问模式 单机读写
  persistentVolumeReclaimPolicy: Recycle  #回收策略,pvc自动清除PV中的数据
  storageClassName: nfs #PV的类型 nfs
  nfs:
    path: /data/nfs1 #存储路径
    server: 118.25.154.214 #服务器IP
---
apiVersion: v1
kind: PersistentVolume #创建PV
metadata:
  name: nfspv2 #PV的名字
spec:
  capacity:
    storage: 5Gi
  accessModes:
    - ReadWriteOnce #访问模式 单机读写
  persistentVolumeReclaimPolicy: Recycle  #回收策略,pvc自动清除PV中的数据
  storageClassName: nfs #PV的类型 nfs
  nfs:
    path: /data/nfs2 #存储路径
    server: 118.25.154.214 #服务器IP
---
apiVersion: v1
kind: PersistentVolume #创建PV
metadata:
  name: nfspv3 #PV的名字
spec:
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteOnce #访问模式 单机读写
  persistentVolumeReclaimPolicy: Recycle  #回收策略,pvc自动清除PV中的数据
  storageClassName: nfs #PV的类型 nfs
  nfs:
    path: /data/nfs3 #存储路径
    server: 118.25.154.214 #服务器IP
---
apiVersion: v1
kind: PersistentVolume #创建PV
metadata:
  name: nfspv4 #PV的名字
spec:
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteOnce #访问模式 单机读写
  persistentVolumeReclaimPolicy: Recycle  #回收策略,pvc自动清除PV中的数据
  storageClassName: slow #PV的类型 slow
  nfs:
    path: /data/nfs4 #存储路径
    server: 118.25.154.214 #服务器IP

3.应用资源文件

kubectl apply -f pv.yaml

4.查看PV

kubectl get pv

在这里插入图片描述

5.暴露多个nfs目录

在nfs服务器上做如下操作

vi /etc/exports  内容如下:
/data/nfs1      *(insecure,rw,no_root_squash,no_all_squash,sync)
/data/nfs2      *(insecure,rw,no_root_squash,no_all_squash,sync)
/data/nfs3      *(insecure,rw,no_root_squash,no_all_squash,sync)
/data/nfs4      *(insecure,rw,no_root_squash,no_all_squash,sync)
# 创建四个目录
mkdir /data/nfs2
mkdir /data/nfs3
mkdir /data/nfs4
# 重启服务
systemctl restart rpcbind.service && systemctl restart nfs.service
#测试共享是否成功
showmount -e 118.25.154.214
3.4.3.3 创建服务并使用PVC

1.创建资源文件

vi pvc.yaml

2.加入内容

apiVersion: v1
kind: Service
metadata:
  name: myappservice
  labels:
    app: myappservice
spec:
  type: ClusterIP
  clusterIP: "None"
  selector:
      app: myapp
  ports:
    - name: http
      port: 8080  
      targetPort: 8080
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: myappsfs
spec:
  replicas: 2
  selector:
    matchLabels:
      app: myapp
  serviceName: "myappservice"
  template:  
    metadata:
      labels:
        app: myapp
    spec:
      containers:
      - name: myapp
        image: tomcat:v1
        ports:
          - name: http
            containerPort: 8080
        volumeMounts:
          - name: vol
            mountPath: /usr/local/tomcat/webapps/ROOT/
  volumeClaimTemplates:  
    - metadata:  
        name: vol
      spec:  
        accessModes: ["ReadWriteOnce"]
        storageClassName: "nfs"
        resources:
          requests: 
            storage: 1Gi

应用资源

kubectl apply -f pvc.yaml

kubectl get pvc

在这里插入图片描述
在这里插入图片描述

修改nfs服务器资源

Echo ‘whale to here’ >  /data/nfs1/index.html 

查看容器

kubectl get pod -o wide

[root@k8smaster ~]# curl 192.168.32.155:8080
whale to here

删除资源

kubectl delete -f pvc.yaml
kubectl delete pvc --all
kubectl delete -f pv.yaml

修改pvc为2,从小到大选择

3.4.4 关于StatefulSet
● 匹配Pod name (网络标识)的模式为: $(statefulset名称)-$(序号), 比如.上面的示例: web-0, web-1,web-2
● StatefulSet 为每个Pod副本创建了-一个DNS域名,这个域名的格式为: $(podname).(headless servername),也就意味着服务间是通过Pod域名来通信而非Pod IP,因为当Pod所在Node发生故障时,Pod 会
被飘移到其它Node上,Pod IP 会发生变化,但是Pod域名不会有变化
● StatefulSet 使用Headless服务来控制Pod的域名,这个域名的FQDN为: $(servicename),.$(namespace).svc.cluster.local,其中,"cluster.local" 指的是集群的域名
● 根据volumeClaimTemplates, 为每个Pod创建-个pvc, pvc 的命名规则匹配模式:
(volumeClaimTemplates.name)-(pod_ name),比如上面的volumeMounts.name=www,Pod
name=web-[0-2],因此创建出来的PVC是www-web-0. www-web-1. www-web-2
● 删除Pod不会删除其pvc,手动删除pvc将自动释放pv
Statefulset的启停顺序:
● 有序部署:部署StatefulSet时, 如果有多个Pod副本,它们会被顺序地创建(从0到N-1)并且,在下- -个
Pod运行之前所有之前的Pod必须都是Running和Ready状态。
● 有序删除:当Pod被删除时,它们被终止的顺序是从N-1到0。
● 有序扩展:当对Pod执行扩展操作时,与部署-样,它前面的Pod必须都处于Running和Ready状态。
StatefulSet使用场景: .
● 稳定的持久化存储,即Pod重新调度后还是能访问到相同的持久化数据,基于PVC来实现。
● 稳定的网络标识符,即Pod重新调度后其PodName和HostName不变。
● 有序部署,有序扩展,基于init containers来实现。
● 有序收缩。.

4.存储型资源-特殊存储卷ConfigMap,Secret

4.1.ConfigMap

ConfigMap功能在Kubernetes1.2版本中引入,许多应用程序会从配置文件、命令行参数或环境变量中读取配置信息。ConfigMap API给我们提供了向容器中注入配置信息的机制,ConfigMap 可以被用来保存单个属性,也可以用来保存整个配置文件或者JSON二进制大对象

4.1.1 创建ConfigMap方式
  1. 方式1:通过字面值创建
    kubectl create configmap my-config --from-literal=key1=config1 --from-literal=key2=config2
    kubectl get cm

  2. 使用文件创建
    kubectl create configmap my-config-2 --from-file=/etc/resolv.conf
    key的名称是文件名称,value的值是这个文件的内容
    kubectl describe cm my-config-2

  3. 使用目录创建
    kubectl create configmap my-config-3 --from-file=test
    test下面放 hosts和/etc/resolv.conf
    目录中的文件名为key,文件内容是value
    Kubectl describe cm my-config-3

  4. 编写configmap的yaml文件

vim cm1.yaml

apiVersion: v1
kind: ConfigMap
metadata:
  name: cm1-config
data:
  db_host: "172.25.0.250"
  db_port: "3306"

kubectl create -f cm1.yaml
kubectl describe cm cm1-config
4.1.2 使用ConfigMap

1)使用ConfigMap来设置环境变量
普通格式

vim cmpod1.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod1
spec:
  containers:
    - name: pod1
      image: busybox
      command: ["/bin/sh", "-c", "env"]
      env:
        - name: key1
          valueFrom:
            configMapKeyRef:
              name: cm1-config
              key: db_host
        - name: key2
          valueFrom:
            configMapKeyRef:
              name: cm1-config
              key: db_port
  restartPolicy: Never
Kubectl apply -f cmpod1.yaml
kubectl logs pod1
kubectl logs pod1 | grep key1
kubectl logs pod1 | grep key2

envfrom格式:Kubernetes在1.6版本引入新字段envFrom,可以实现在Pod环境中将ConfigMap中所有定义的key=value自动生成为环境变量

vim cmpod2.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod2
spec:
  containers:
    - name: pod2
      image: busybox
      command: ["/bin/sh", "-c", "env"]
      envFrom:
        - configMapRef:
            name: cm1-config
  restartPolicy: Never
kubectl logs pod2

2)使用configmap设置命令行参数

vim cmpod3.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod3
spec:
  containers:
    - name: pod3
      image: busybox
      command: ["/bin/sh", "-c", "echo $(db_host) $(db_port)"]
      envFrom:
        - configMapRef:
            name: cm1-config
  restartPolicy: Never
kubectl create -f cmpod3.yaml 
kubectl logs pod3

3)通过数据卷使用configmap

vim cmpod4.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod4
spec:
  containers:
    - name: pod4
      image: busybox
      command: ["/bin/sh", "-c", "cat /config/db_host"]   
      volumeMounts:
      - name: config-volume
        mountPath: /config #容器重点数据卷目录
  volumes:
    - name: config-volume
      configMap:
        name: cm1-config #他会吧confMap中数据的key作为文件名同步到数据卷目录
kubectl create -f cmpod4.yaml 
kubectl logs pod4 
4.1.3 热更新ConfigMap
vim cmdeploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: cm-deploy-example
spec:
  replicas: 2
  selector:
    matchLabels:
      app: cm-deploy-demo
  template:
    metadata:
      labels:
        app: cm-deploy-demo
    spec:
      containers:
      - name: myapp
        image: tomcat:v1
        ports:
        - name: http
          containerPort: 8080
        volumeMounts:
          - name: config-volume
            mountPath: /config
      volumes:
        - name: config-volume
          configMap:
            name: cm1-config
kubectl apply -f cmdeploy.yaml
kubectl exec cm-deploy-example-65947f596-7ksql cat /config/db_port
kubectl edit cm cm1-config     修改后过一段时间刷新数据卷
4.2.Secret

ConfigMap是用来存储一些非安全的配置信息,如果涉及到一些安全相关的数据的话用ConfigMap就非常不妥了,因为ConfigMap明文存储的,这个时候使用Secret,Secret用来保存敏感信息,例如密码、OAuth 令牌和 ssh key等等,将这些信息放在Secret中比放在Pod的定义中或者docker镜像中来说更加安全和灵活。
Secret有三种类型:

  • Opaque:base64 编码格式的 Secret,用来存储密码、密钥等;但数据也可以通过base64 –decode解码得到原始数据,所有加密性很弱。
  • kubernetes.io/dockerconfigjson:用来存储私有docker registry的认证信息。
  • kubernetes.io/service-account-token:用于被serviceaccount引用,serviceaccout 创建时Kubernetes会默认创建对应的secret。Pod如果使用了serviceaccount,对应的secret会自动挂载到Pod目录/run/secrets/kubernetes.io/serviceaccount中。
4.2.1 Opaque Secret

Opaque 类型的数据是一个 map 类型,要求value是base64编码格式。
比如我们来创建一个用户名为 zhangsan,密码为 zhangsan 的 Secret 对象,
首先我们先把这用户名和密码做 base64 编码
在这里插入图片描述

1.创建配置

vi secret-opaque.yaml
apiVersion: v1
kind: Secret
metadata:
  name: mysecret
type: Opaque
data:
  username: emhhbmdzYW4K
  password: emhhbmdzYW4K
创建:kubectl create -f secret-opaque.yaml 
查看:kubectl get secret
查看:kubectl get secret mysecret

2.使用配置 - 作为环境变量

vi test-secret-opaque-env-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: secret-opaque-env-pod
spec:
  containers:
  - name: secret-opaque-env-pod
    image: busybox
    command: [ "/bin/sh", "-c", "env" ]
    env:
    - name: USERNAME
      valueFrom:
        secretKeyRef:
          name: mysecret
          key: username
    - name: PASSWORD
      valueFrom:
        secretKeyRef:
          name: mysecret
          key: password
kubectl apply -f test-secret-opaque-env-pod.yaml

kubectl logs secret-opaque-env-pod

3.作为存储卷

vi test-secret-opaque-volume.yaml
apiVersion: v1
kind: Pod
metadata:
  name: secret-opaque-volume
spec:
  containers:
  - name: secret2
    image: tomcat:v1
    command: ["/bin/sh", "-c", "ls /etc/secrets"]
    volumeMounts:
    - name: secrets
      mountPath: /etc/secrets
  volumes:
  - name: secrets
    secret:
     secretName: mysecret
kubectl apply -f test-secret-opaque-volume.yaml
kubectl logs secret-opaque-volume
可以看到secret把两个key挂载成了两个对应的文件
4.2.2 kubernetes.io/dockerconfigjson

用来docker registry认证,直接使用kubectl create命令创建即可,如下

kubectl create secret docker-registry dockersecret --docker-server=172.16.10.190 --docker-username=admin --docker-password=admin123 --docker-email=admin@example.org
[root@k8smaster ~]# kubectl describe secret dockersecret

Name:         dockersecret
Namespace:    default
Labels:       <none>
Annotations:  <none>

Type:  kubernetes.io/dockerconfigjson

Data
====
.dockerconfigjson:  128 bytes

这里是把docker registry的认证信息存储到了.dockerconfigjson中,

可以解码查看上面的数据的base64解码

apiVersion: v1
kind: Pod
metadata:
  name: foo
spec:
  containers:
    - name: foo
      image: roc/awangyang:v1
  imagePullSecrets:
    - name: dockersecret #跟上该名字,以后默认直接带dockersecret 对应的用户名和密码去拉镜像
4.2.3 kubernetes.io/service-account-token

另外一种Secret类型就是kubernetes.io/service-account-token,用于被serviceaccount引用。serviceaccout 创建时 Kubernetes 会默认创建对应的 secret。Pod 如果使用了 serviceaccount,对应的secret会自动挂载到Pod的/run/secrets/kubernetes.io/serviceaccount目录中。

部署dashboard时使用过这种方式
创建一个cluster-admin角色的service account , 和一个clusterrolebinding, 以便访问所有的k8s资源

kubectl create serviceaccount cluster-admin-dashboard-sa
kubectl create clusterrolebinding cluster-admin-dashboard-sa \
  --clusterrole=cluster-admin \
  --serviceaccount=default:cluster-admin-dashboard-sa

kubectl get secret | grep cluster-admin-dashboard-sa
kubectl describe secrets/cluster-admin-dashboard-sa-token-hld8l
4.3.小结
Secret 与 ConfigMap 对比
相同点:
	key/value的形式
	属于某个特定的namespace
	可以导出到环境变量
	可以通过目录/文件形式挂载
	通过 volume 挂载的配置信息均可热更新
不同点:
    Secret 可以被 ServerAccount 关联
	Secret 可以存储 docker register 的鉴权信息,用在 ImagePullSecret 参数中,用于拉取私有仓库的镜像
	Secret 支持 Base64 加密
	Secret 分为 kubernetes.io/service-account-token、kubernetes.io/dockerconfigjson、Opaque 三种类型,而 Configmap 不区分类型

5. 和Springcloud集成

5.1.Spring-cloud-kubernetes

Spring-cloud-kubernetes是springcloud官方推出的开源项目,用于将Spring Cloud和Spring Boot应用运行在kubernetes环境,并且提供了通用的接口来调用kubernetes服务,GitHub上官方地址是:https://github.com/spring-cloud/spring-cloud-kubernetes

5.2.思路分析

在这里插入图片描述
使用ConfigMap代替Config配置中心,使用Service代替Eureak服务发现
在这里插入图片描述
具体实现见案例https://blog.csdn.net/boling_cavalry/article/details/91346780

6.课程总结

6.1.重点

1.学习

6.2.难点

1.记住

7.常见异常

8.课后练习

9.面试题

10.扩展知识或课外阅读推荐

10.1.扩展知识

看官方资料,PDF书

10.2.课外阅读
Logo

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

更多推荐