原文内容:https://gitee.com/dev-99cloud/training-kubernetes ,在此基础上有新增。

Lesson 07: Service

7.1 Service 在底层是怎么实现的?

7.2 实验:发布服务

  • Cluster IP
  • Service FQDN
  • Nodeport
  • LB Type Service
# Taint slave 节点,因为在有些环境中没有放开隧道防火墙,我们强制让 pod 都跑在 master 上
kubectl taint node ckaslave001 key=value:NoExecute

# 创建 Deployment
kubectl apply -f https://raw.githubusercontent.com/kubernetes/website/master/content/en/examples/service/networking/run-my-nginx.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-nginx
spec:
  selector:
    matchLabels:
      run: my-nginx
  replicas: 2
  template:
    metadata:
      labels:
        run: my-nginx
    spec:
      containers:
      - name: my-nginx
        image: nginx
        ports:
        - containerPort: 80
# 创建 Service
kubectl apply -f https://raw.githubusercontent.com/kubernetes/website/master/content/en/examples/service/networking/nginx-svc.yaml
apiVersion: v1
kind: Service
metadata:
  name: my-nginx
  labels:
    run: my-nginx
spec:
  ports:
  - port: 80
    protocol: TCP
  selector:
    run: my-nginx
root@ckamaster001:~# kubectl get svc --all-namespaces -o wide
NAMESPACE     NAME         TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)                  AGE   SELECTOR
default       kubernetes   ClusterIP   10.96.0.1      <none>        443/TCP                  8h    <none>
default       my-nginx     ClusterIP   10.98.172.84   <none>        80/TCP                   36m   run=my-nginx
kube-system   kube-dns     ClusterIP   10.96.0.10     <none>        53/UDP,53/TCP,9153/TCP   8h    k8s-app=kube-dns

root@ckamaster001:~# dig @10.96.0.10 my-nginx.default.svc.cluster.local

; <<>> DiG 9.11.3-1ubuntu1.12-Ubuntu <<>> @10.96.0.10 my-nginx.default.svc.cluster.local
; (1 server found)
;; global options: +cmd
;; Got answer:
;; WARNING: .local is reserved for Multicast DNS
;; You are currently testing what happens when an mDNS query is leaked to DNS
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 23475
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
; COOKIE: 2661e0af4b0ce87e (echoed)
;; QUESTION SECTION:
;my-nginx.default.svc.cluster.local. IN	A

;; ANSWER SECTION:
my-nginx.default.svc.cluster.local. 30 IN A	10.98.172.84

;; Query time: 0 msec
;; SERVER: 10.96.0.10#53(10.96.0.10)
;; WHEN: Sat Jun 13 16:15:23 CST 2020
;; MSG SIZE  rcvd: 125

7.3 什么是 Ingress?

  • Ingress Controller

    • 安装 Nginx Ingress Controller

      # 下载 ingress controller 的 yaml 文件
      # wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.3.0/deploy/static/provider/cloud/deploy.yaml
      wget https://gitee.com/dev-99cloud/training-kubernetes/raw/master/src/amd-lab/deploy.yaml
      

      新版本默认不监听 80、443 端口,需自行进行配置

      # 查看端口是否被占用
      # lsof -i :xxx
      netstat -putln | grep 80
      netstat -putln | grep 443
      # 修改 deploy.yaml 文件,在 Deployment 的 spec.template.spec 处添加如下语句可监听本地端口
      hostNetwork: true
      
      # spec:
      #  hostNetwork: true
      #  containers:
      #  - name: nginx
      #    image: nginx:1.7.9
      
      # 一般 443 会被 calico 占用,80 端口不会被占用,可以注释掉文件中名为 ingress-nginx-controller 的 deployment 和 service 的 ports 处关于 443 的内容, controller 将不会再监听 443 端口
      
      # 安装 ingress controller
      kubectl apply -f deploy.yaml
      # 查看
      kubectl get pods -n ingress-nginx
      kubectl get svc -n ingress-nginx
      # 可以看到 ingress-nginx-controller 的 EXTERNAL-IP 状态为 pending,需要我们手动添加 externalIPs
      
      # 在 ingress-nginx-controller service 的 spec 下添加,10.0.0.118 为节点内网 ip :
      #   externalIPs:
      #   - 10.0.0.118
      
      # spec:
      #  externalIPs:
      #  - 192.168.132.253
      #  ports:
      #   - name: highport
      #     nodePort: 31903
      
      kubectl edit svc ingress-nginx-controller -n ingress-nginx
      
  • Ingress

    • 部署后端服务

      [root@iZuf6g226c4titrnrwds2tZ ~]# vim deploy-demo.yaml
      
      apiVersion: v1
      kind: Service
      metadata:
        name: myapp
        namespace: default
      spec:
        selector:
          app: myapp
          release: canary
        ports:
        - name: http
          targetPort: 80
          port: 80
      ---
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: myapp-backend-pod
        namespace: default
      spec:
        replicas: 3
        selector:
          matchLabels:
            app: myapp
            release: canary
        template:
          metadata:
            labels:
              app: myapp
              release: canary
          spec:
            containers:
            - name: myapp
              image: ikubernetes/myapp:v2
              ports:
              - name: http
                containerPort: 80
      
      [root@iZuf6g226c4titrnrwds2tZ ~]# kubectl apply -f deploy-demo.yaml
      [root@iZuf6g226c4titrnrwds2tZ ~]# kubectl get pods
      NAME                                 READY   STATUS    RESTARTS   AGE
      myapp-backend-pod-58b7f5cf77-krmzh   1/1     Running   2          17h
      myapp-backend-pod-58b7f5cf77-vqlgl   1/1     Running   2          17h
      myapp-backend-pod-58b7f5cf77-z7j7z   1/1     Running   2          17h
      
    • 通过 ingress-controller 对外提供服务,还要为其建立一个 service

      #下载 yaml 文件
      wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/provider/baremetal/service-nodeport.yaml
      vim 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
            nodePort: 30080
          - name: https
            port: 443
            targetPort: 443
            protocol: TCP
            nodePort: 30443
        selector:
          app.kubernetes.io/name: ingress-nginx
          app.kubernetes.io/part-of: ingress-nginx
      
      ---
      
      [root@iZuf6g226c4titrnrwds2tZ ~]# kubectl apply -f service-nodeport.yaml
      [root@iZuf6g226c4titrnrwds2tZ ~]# kubectl get svc -n ingress-nginx
      NAME            TYPE       CLUSTER-IP       EXTERNAL-IP   PORT(S)                      AGE
      ingress-nginx   NodePort   10.105.153.191   <none>        80:30080/TCP,443:30443/TCP   9h
      
    • 部署 Ingress

      [root@iZuf6g226c4titrnrwds2tZ ~]# vim ingress-myapp.yaml
      
      apiVersion: networking.k8s.io/v1
      kind: Ingress
      metadata:
        name: ingress-myapp
        namespace: default
        annotations:
          kubernetes.io/ingress.class: "nginx"
      spec:
        rules:
        - host: myapp.test.com
          http:
            paths:
            - path: /
              pathType: Prefix
              backend:
                service:
                  name: myapp
                  port:
                    number: 80
      
      [root@iZuf6g226c4titrnrwds2tZ ~]# kubectl apply -f ingress-myapp.yaml
      [root@iZuf6g226c4titrnrwds2tZ ~]# kubectl get ingress
      NAME            CLASS    HOSTS            ADDRESS          PORTS   AGE
      ingress-myapp   <none>   myapp.test.com   10.105.153.191   80      17h
      
    • 结果测试

      # 修改本地 host 文件
      sudo vi /etc/hosts
      # 添加
      xxx.xxx.xxx.xxx myapp.test.com
      # 终端访问
      curl http://myapp.test.com
      # 结果
      Hello MyApp | Version: v2 | <a href="hostname.html">Pod Name</a>
      # 在外部访问时可能出现网站未备案的问题,多次尝试即可
      # 在内部也需配置 hosts 通过域名进行访问
      
    • k8s.gcr.io 网络问题导致镜像 pull 失败

      • 将 yaml 文件下载到本地

      • 在 docker hub 上搜索对应的images

      • 将文件内对应的 image 修改为 docker hub 上搜索到的对应 image ,如:

        #image: k8s.gcr.io/ingress-nginx/controller:v0.47.  0@sha256:52f0058bed0a17ab0fb35628ba97e8d52b5d32299fbc03cc0f6c7b9ff036b61a
        image: willdockerhub/ingress-nginx-controller:v0.47.0
        
      • kubectl apply -f xxx `