五、Kubernetes 實(shí)戰(zhàn)項(xiàng)目搭建

1、步驟梳理

本章節(jié)將主要圍繞實(shí)戰(zhàn)搭建項(xiàng)目為主,既然是實(shí)戰(zhàn),就得考慮好需要準(zhǔn)備哪些東西,所有的準(zhǔn)備都做好了,才能正確的往下進(jìn)行。本章節(jié)目的在于把之前學(xué)習(xí)的知識(shí)點(diǎn)進(jìn)行一次串聯(lián),加深一下映像!

本次實(shí)戰(zhàn)準(zhǔn)備了三個(gè)案例:

  • WordPress + MySQL
  • Spring Boot項(xiàng)目
  • Nacos服務(wù)注冊與發(fā)現(xiàn)

每個(gè)案例都會(huì)以不同的通信方式去部署。

1.1、服務(wù)搭建步驟

  • 確定自己當(dāng)前的服務(wù)有哪些
  • 服務(wù)是官方的還是自定義的
    • 若是自定義則需要編寫Dockerfile
    • 自定義的鏡像上傳鏡像倉庫 【可選】
  • 服務(wù)隔離【可選】
    • 服務(wù)很多的情況下,為了方便管理,一般會(huì)創(chuàng)建一個(gè)獨(dú)立的命名空間為這個(gè)項(xiàng)目使用
  • 創(chuàng)建服務(wù)所需的 YAML 文件
  • 服務(wù)發(fā)現(xiàn)的策略
    • 通過 Service NodePort實(shí)現(xiàn)集群內(nèi)部通信
    • 通過 Ingress 實(shí)現(xiàn)集群內(nèi)外通信
  • 服務(wù)監(jiān)控、日志收集等 【暫不實(shí)現(xiàn)】
    • 本章不演示,因?yàn)槟壳斑€沒有開始學(xué)習(xí)到這部分,等到后面再慢慢分享!

2、項(xiàng)目搭建

2.1、WordPress + MySQL

2.1.1 搭建說明

  • 2個(gè)服務(wù)都使用官方 image,所以無需編寫Dockerfile
  • 創(chuàng)建命名空間
  • 編寫 YAML 文件
    • mysql 服務(wù)我們只給wordpress訪問,所以直接用 ClusterIP方式實(shí)現(xiàn)集群內(nèi)通信即可。
    • wordpress 服務(wù)需要外部訪問,使用NodePort方式進(jìn)行通信。

2.1.2 服務(wù)搭建

  • 創(chuàng)建 WordPress 命名空間

    [root@master-kubeadm-k8s wordpress]# kubectl create namespace wordpress
    namespace/wordpress created
    
  • 創(chuàng)建 wordpress-db.yaml 文件

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: mysql-deploy
      namespace: wordpress                                  # 指定命名空間
      labels:
        app: mysql
    spec:
      selector:
        matchLabels:
          app: mysql
      template:
        metadata:
          labels:
            app: mysql
        spec:
          nodeSelector: 
            name: ingress                 # 這里增加 節(jié)點(diǎn)選擇器 , 前面章節(jié)我們?yōu)?worker01 節(jié)點(diǎn)創(chuàng)建了 name: ingress 標(biāo)簽,這里用一下
          containers:
          - name: mysql
            image: mysql:5.6
            imagePullPolicy: IfNotPresent   # 拉取策略,本地有則使用本地鏡像,不拉取
            ports:
            - containerPort: 3306
              name: dbport
            env:
            - name: MYSQL_ROOT_PASSWORD             # 定義mysql root用戶密碼
              value: root
            - name: MYSQL_DATABASE                  # 創(chuàng)建一個(gè)數(shù)據(jù)庫 名為 wordpress
              value: wordpress
            - name: MYSQL_USER                              # wordpress數(shù)據(jù)庫的用戶名
              value: wordpress
            - name: MYSQL_PASSWORD                  # wordpress數(shù)據(jù)庫的密碼
              value: wordpress
            volumeMounts:                                   # 指定容器的映射目錄
            - name: db
              mountPath: /var/lib/mysql
          volumes:                                                  # 指定宿主機(jī)的映射目錄
          - name: db
            hostPath:
              path: /var/lib/mysql
    ---
    # 定義 Service 資源
    apiVersion: v1
    kind: Service
    metadata:
      name: mysql
      namespace: wordpress
    spec:
      type: NodePort
      selector:
        app: mysql
      ports:
      - name: mysqlport
        protocol: TCP
        port: 3306
        targetPort: dbport
    
  • 創(chuàng)建 wordpress.yaml 文件

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: wordpress-deploy
      namespace: wordpress
      labels:
        app: wordpress
    spec:
      selector:
        matchLabels:
          app: wordpress
      template:
        metadata:
          labels:
            app: wordpress
        spec:
          containers:
          - name: wordpress
            image: wordpress
            imagePullPolicy: IfNotPresent
            ports:
            - containerPort: 80
              name: wdport
            env:
            - name: WORDPRESS_DB_HOST         # 指定數(shù)據(jù)庫ip:port
              value: 10.104.83.208:3306        # 這里用mysql的service的ip、名稱或pod的ip都可以
            - name: WORDPRESS_DB_USER         # 指定數(shù)據(jù)庫用戶名
              value: wordpress
            - name: WORDPRESS_DB_PASSWORD     # 指定數(shù)據(jù)庫密碼
              value: wordpress
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: wordpress
      namespace: wordpress
    spec:
      type: NodePort                          # 指定 Service 網(wǎng)絡(luò)模式
      selector:
        app: wordpress
      ports:
      - name: wordpressport
        protocol: TCP
        port: 80
        targetPort: wdport
    
  • 創(chuàng)建資源

    # 創(chuàng)建 wordpress-db
    [root@master-kubeadm-k8s wordpress]# kubectl apply -f wordpress-db.yaml
    deployment.apps/mysql-deploy created
    service/mysql created
    
    # 創(chuàng)建 wordpress
    [root@master-kubeadm-k8s wordpress]# kubectl apply -f wordpress.yaml
    deployment.apps/wordpress-deploy created
    service/wordpress created
    
    # 查看 Pod
    [root@master-kubeadm-k8s wordpress]# kubectl get pods -n wordpress
    NAME                                READY   STATUS    RESTARTS   AGE
    mysql-deploy-868f4cbd7b-chkw5       1/1     Running   0          4m10s
    wordpress-deploy-5c898774dc-8kckq   1/1     Running   0          2m55s
    
    # 查看 Service,得到 nodePort 32731
    [root@master-kubeadm-k8s wordpress]# kubectl get svc -n wordpress
    NAME        TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
    mysql       ClusterIP   10.104.83.208    <none>        3306/TCP       3m14s
    wordpress   NodePort    10.100.137.131   <none>        80:32731/TCP   2m56s
    
  • 測試

    訪問宿主機(jī) ip:32731

    image.png

若出現(xiàn)訪問不通的情況, 可以在宿主機(jī)執(zhí)行 iptables -P FORWARD ACCEPT 命令就可以解決

2.2、Spring Boot 項(xiàng)目部署

2.2.1 搭建說明

  • 準(zhǔn)備服務(wù),生成 Jar 文件并上傳服務(wù)器
  • 服務(wù)是自己的項(xiàng)目代碼,需要編寫Dockerfile
  • 鏡像上傳鏡像倉庫
  • 編寫 YAML 文件
    • 為了供外部訪問,采用 Ingress controller方式進(jìn)行通信

2.2.2 服務(wù)搭建

  • 準(zhǔn)備服務(wù)

    image.png
  • 準(zhǔn)備 Jar 包并上傳至服務(wù)器

  • 編寫Dockerfile并生成 image

    FROM openjdk:8-jre-alpine
    COPY springboot-demo-0.0.1-SNAPSHOT.jar /springboot-demo.jar
    ENTRYPOINT ["java","-jar","/springboot-demo.jar"]
    
    [root@master-kubeadm-k8s k8s-springboot-demo]# vi Dockerfile
    
    # 生成 springboot-demo-image
    [root@master-kubeadm-k8s k8s-springboot-demo]# docker build -t springboot-demo-image .
    Sending build context to Docker daemon   17.6MB
    Step 1/3 : FROM openjdk:8-jre-alpine
    8-jre-alpine: Pulling from library/openjdk
    e7c96db7181b: Pull complete
    f910a506b6cb: Pull complete
    b6abafe80f63: Pull complete
    Digest: sha256:f362b165b870ef129cbe730f29065ff37399c0aa8bcab3e44b51c302938c9193
    Status: Downloaded newer image for openjdk:8-jre-alpine
     ---> f7a292bbb70c
    Step 2/3 : COPY springboot-demo-0.0.1-SNAPSHOT.jar /springboot-demo.jar
     ---> 40cbd786e301
    Step 3/3 : ENTRYPOINT ["java","-jar","/springboot-demo.jar"]
     ---> Running in 79f29aff270c
    Removing intermediate container 79f29aff270c
     ---> 845f0d0b2d7f
    Successfully built 845f0d0b2d7f
    Successfully tagged springboot-demo-image:latest
    
  • 上傳至阿里云鏡像倉庫

    # 1、登錄阿里云鏡像倉庫
    [root@master-kubeadm-k8s k8s-springboot-demo]# sudo docker login --username=【用戶名】 registry.cn-hangzhou.aliyuncs.com
    Password:
    WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
    Configure a credential helper to remove this warning. See
    https://docs.docker.com/engine/reference/commandline/login/#credentials-store
    Login Succeeded
    
    # 2、打 tag
    docker tag springboot-demo-image registry.cn-hangzhou.aliyuncs.com/【命名空間】/springboot-demo-image:v1.0
    
    # 3、上傳鏡像
    [root@master-kubeadm-k8s k8s-springboot-demo]# docker push registry.cn-hangzhou.aliyuncs.com/sunny95/springboot-demo-image:v1.0
    The push refers to repository [registry.cn-hangzhou.aliyuncs.com/sunny95/springboot-demo-image]
    2b85a76d2ba6: Pushed
    edd61588d126: Pushed
    9b9b7f3d56a0: Pushed
    f1b5933fe4b5: Pushed
    v1.0: digest: sha256:d9cd5f2ebd86c3e0c01064156c508c9ea557a8e8df0ae2f79be190844bb4b980 size: 1159
    
    image.png
  • 編寫 YAML 文件

    apiVersion: apps/v1
    kind: Deployment
    metadata: 
      name: springboot-demo
    spec: 
      selector: 
        matchLabels: 
          app: springboot-demo
      replicas: 1
      template: 
        metadata:
          labels: 
            app: springboot-demo
        spec: 
          containers: 
          - name: springboot-demo
          # 這里就使用我們上傳的鏡像倉庫的image
            image: registry.cn-hangzhou.aliyuncs.com/sunny95/springboot-demo-image:v1.0
            ports: 
            - containerPort: 8080
    ---
    # 創(chuàng)建Pod的Service
    apiVersion: v1
    kind: Service
    metadata: 
      name: springboot-demo
    spec: 
      ports: 
      - port: 80
        protocol: TCP
        targetPort: 8080
      selector: 
        app: springboot-demo
    ---
    # 創(chuàng)建Ingress,定義訪問規(guī)則,一定要記得提前創(chuàng)建好nginx ingress controller
    apiVersion: networking.k8s.io/v1beta1
    kind: Ingress
    metadata: 
      name: springboot-demo
    spec: 
      rules: 
      - host: tomcat.sunny.com    # windows hosts中配置了與宿主機(jī)ip對(duì)應(yīng)的域名
        http: 
          paths: 
          - path: /
            backend: 
              serviceName: springboot-demo
              servicePort: 80
    

    因?yàn)樵谥暗恼鹿?jié)演示中,我們已經(jīng)創(chuàng)建好了 Ingress Controller,所以這里直接寫 Ingress規(guī)則即可

  • 創(chuàng)建資源

    # 創(chuàng)建資源
    [root@master-kubeadm-k8s k8s-springboot-demo]# kubectl apply -f springboot-demo.yaml
    deployment.apps/springboot-demo created
    service/springboot-demo created
    ingress.networking.k8s.io/springboot-demo created
    
    # 查看 Pod, 發(fā)現(xiàn)還沒創(chuàng)建好
    [root@master-kubeadm-k8s k8s-springboot-demo]# kubectl get pods
    NAME                               READY   STATUS              RESTARTS   AGE
    springboot-demo-5f6f5c9696-66vvm   0/1     ContainerCreating   0          8s
    
    # 看下 Pod 描述, 看當(dāng)前在做什么
    [root@master-kubeadm-k8s k8s-springboot-demo]# kubectl describe pod springboot-demo-5f6f5c9696-5gj9k
    # ...省略...
    
    # ===================== 發(fā)現(xiàn)拉取鏡像失敗了 ======================
    Events:
      Type     Reason     Age   From                           Message
      ----     ------     ----  ----                           -------
      Normal   Scheduled  57s   default-scheduler              Successfully assigned default/springboot-demo-5f6f5c9696-5gj9k to worker01-kubeadm-k8s
      Normal   Pulling    55s   kubelet, worker01-kubeadm-k8s  Pulling image "registry.cn-hangzhou.aliyuncs.com/sunny95/springboot-demo-image:v1.0"
      Warning  Failed     5s    kubelet, worker01-kubeadm-k8s  Failed to pull image "registry.cn-hangzhou.aliyuncs.com/sunny95/springboot-demo-image:v1.0": rpc error: code = Unknown desc = Error response from daemon: pull access denied for registry.cn-hangzhou.aliyuncs.com/sunny95/springboot-demo-image, repository does not exist or may require 'docker login'
      Warning  Failed     5s    kubelet, worker01-kubeadm-k8s  Error: ErrImagePull
      Normal   BackOff    4s    kubelet, worker01-kubeadm-k8s  Back-off pulling image "registry.cn-hangzhou.aliyuncs.com/sunny95/springboot-demo-image:v1.0"
      Warning  Failed     4s    kubelet, worker01-kubeadm-k8s  Error: ImagePullBackOff
    

    其實(shí)這是權(quán)限問題,K8S需要有一個(gè)認(rèn)證才能從私有倉庫拉取鏡像,可以創(chuàng)建 Secret 解決

    如果是公開庫就可以正常拉取,不會(huì)出現(xiàn)這種問題

    • 解決K8S拉取不了私有鏡像倉庫的問題

       # 在集群中創(chuàng)建保存授權(quán)令牌的 Secret
      [root@master-kubeadm-k8s k8s-springboot-demo]# kubectl create secret docker-registry [自定義secret名稱] --docker-server=registry.cn-hangzhou.aliyuncs.com --docker-username=[用戶名] --docker-password=[密碼] --docker-email=[郵箱]
      secret/registry-aliyun created
            
      # 檢查 Secret
      [root@master-kubeadm-k8s k8s-springboot-demo]# kubectl get secret registry-aliyun --output=yaml
      apiVersion: v1
      data:
        .dockerconfigjson: eyJhdXRocyI6eyJyZWdpc3RyeS5jbi1oYW5nemhvdS5hbGl5dW5jcy5jb20iOnsidXNlcm5hbWUiOiJ5enlfemhhb3lhbmdAMTYzLmNvbSIsInBdkjhasjdhksabdkajaksddasdaWwiOiJ5enlfemhhb3lhbmdAMTYzLmNvbSIsImF1dGgiOiJlWHAkcjnhkcnhamoewr3242309jdsjaldj092qeGIxbEJUa2MxTmpJMU5ERTQifX19
      kind: Secret
      metadata:
        creationTimestamp: "2020-04-03T16:50:24Z"
        name: registry-aliyun
        namespace: default
        resourceVersion: "109789"
        selfLink: /api/v1/namespaces/default/secrets/registry-aliyun
        uid: 368a54cd-22ggb-11ea-28ty-5254008afee6
      type: kubernetes.io/dockerconfigjson
      
      • 修改 YAML 文件,增加 Secret認(rèn)證

        apiVersion: apps/v1
        kind: Deployment
        metadata: 
          name: springboot-demo
        spec: 
          selector: 
            matchLabels: 
              app: springboot-demo
          replicas: 1
          template: 
            metadata:
              labels: 
                app: springboot-demo
            spec: 
              containers: 
              - name: springboot-demo
              # 這里就使用我們上傳的鏡像倉庫的image
                image: registry.cn-hangzhou.aliyuncs.com/sunny95/springboot-demo-image:v1.0
                ports: 
                - containerPort: 8080
                #=========增加 Secret===========
              imagePullSecrets:
              - name: registry-aliyun   # 注意名稱要與創(chuàng)建時(shí)指定的名稱一致
                #=========增加 Secret===========
        ---
        # 創(chuàng)建Pod的Service
        apiVersion: v1
        kind: Service
        metadata: 
          name: springboot-demo
        spec: 
          ports: 
          - port: 80
            protocol: TCP
            targetPort: 8080
          selector: 
            app: springboot-demo
        ---
        # 創(chuàng)建Ingress,定義訪問規(guī)則,一定要記得提前創(chuàng)建好nginx ingress controller
        apiVersion: networking.k8s.io/v1beta1
        kind: Ingress
        metadata: 
          name: springboot-demo
        spec: 
          rules: 
          - host: tomcat.sunny.com    # windows hosts中配置了與宿主機(jī)ip對(duì)應(yīng)的域名
            http: 
              paths: 
              - path: /
                backend: 
                  serviceName: springboot-demo
                  servicePort: 80
        
    • 重新創(chuàng)建資源

      # 創(chuàng)建資源
      [root@master-kubeadm-k8s k8s-springboot-demo]# kubectl apply -f springboot-demo.yaml
      deployment.apps/springboot-demo created
      service/springboot-demo created
      ingress.networking.k8s.io/springboot-demo created
      
      # 已經(jīng)創(chuàng)建完成
      [root@master-kubeadm-k8s k8s-springboot-demo]# kubectl get pods
      NAME                               READY   STATUS    RESTARTS   AGE
      springboot-demo-75f846fd48-zpwtw   1/1     Running   0          2m2s
      
  • 查看資源

    # 查看 Service
    [root@master-kubeadm-k8s k8s-springboot-demo]# kubectl get svc
    NAME              TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE
    kubernetes        ClusterIP   10.96.0.1        <none>        443/TCP   10d
    springboot-demo   ClusterIP   10.109.134.133   <none>        80/TCP    4m27s
    
    # 查看 ingress
    [root@master-kubeadm-k8s k8s-springboot-demo]# kubectl get ingress
    NAME              HOSTS              ADDRESS   PORTS   AGE
    springboot-demo   tomcat.sunny.com             80      4m40s
    
  • 測試

    image.png

測試成功訪問到 SpringBoot 服務(wù)

2.3、Nacos 服務(wù)注冊與發(fā)行

2.3.1 搭建說明

  • 準(zhǔn)備Nacos注冊中心
  • 準(zhǔn)備兩個(gè)服務(wù),一個(gè)服務(wù)依賴另一個(gè)服務(wù)
    • user、order服務(wù)
  • 服務(wù)注冊至 Nacos
  • 編寫兩個(gè)服務(wù)的Dockerfile
  • 編寫 YAML 文件
    • Nacos注冊中心這里不通過容器部署,所以就不寫 YAML 文件了

2.3.2 服務(wù)搭建

  • 準(zhǔn)備 Nacos 注冊中心

    注冊中心的選擇是自定義的,這里只是選擇了Nacos作為演示,你也可以選擇其他的注冊中心去測試!

    以單機(jī)模式啟動(dòng) nacos

    image.png

訪問物理機(jī) ip:8848/nacos 即可訪問注冊中心

nacos 默認(rèn)的用戶名:nacos,密碼:nacos

image.png
  • 準(zhǔn)備user、order項(xiàng)目并驗(yàn)證
    • POM 依賴

      注意:Cloud生態(tài)對(duì)版本依賴還是挺大的,如果SpringBoot版本與SpringCloud版本不匹配可能會(huì)出現(xiàn)問題的

      <parent>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-parent</artifactId>
          <version>2.2.1.RELEASE</version>
          <relativePath/> <!-- lookup parent from repository -->
      </parent>
      
      <dependencies>
              <dependency>
                  <groupId>org.springframework.boot</groupId>
                  <artifactId>spring-boot-starter-web</artifactId>
              </dependency>
      
              <!--引入nacos client依賴-->
              <dependency>
                  <groupId>org.springframework.cloud</groupId>
                  <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
              </dependency>
          </dependencies>
      
          <dependencyManagement>
              <dependencies>
                  <!--加入Spring Cloud依賴-->
                  <dependency>
                      <groupId>org.springframework.cloud</groupId>
                      <artifactId>spring-cloud-dependencies</artifactId>
                      <version>Greenwich.SR1</version>
                      <type>pom</type>
                      <scope>import</scope>
                  </dependency>
      
                  <!--加入Spring Cloud Alibaba依賴-->
                  <dependency>
                      <groupId>org.springframework.cloud</groupId>
                      <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                      <version>0.9.0.RELEASE</version>
                      <type>pom</type>
                      <scope>import</scope>
                  </dependency>
              </dependencies>
          </dependencyManagement>
      
    • user 服務(wù)

      • 配置文件

        spring:
          cloud:
            nacos:
              discovery:
                #指定nacos server的地址
                server-addr: 101.55.33.23:8848
          application:
            name: user
        
        server:
          port: 8080
        
      • controller

        @RestController
        @RequestMapping("/user")
        public class TestController {
        
            @Autowired
            private DiscoveryClient discoveryClient;
        
            /**
             * 通過Cloud提供的 DiscoveryClient 來發(fā)現(xiàn)服務(wù)
             */
            @RequestMapping("/test")
            public Map<String, Object> findServiceInstance() throws Exception{
                //查詢指定服務(wù)名稱下的所有實(shí)例的信息
                List<ServiceInstance> list=this.discoveryClient.getInstances("order");
                ServiceInstance serviceInstance=list.get(0);
                URI uri = serviceInstance.getUri();
        
                String testResult = this.testUrl(uri.toString());
        
                Map<String, Object> map = new HashMap<>();
                map.put("service", list);
                map.put("uri", uri.toString());
                
                //保存 能否 ping 通 order 服務(wù)的結(jié)果
                map.put("testResult", testResult);
        
                return map;
            }
        
            /**
             * 測試user服務(wù)能否 ping 通order服務(wù)的ip
             *
             * @param urlString order服務(wù)所在機(jī)器的ip
             */
            public String testUrl(String urlString){
                URL url;
                try {
                    url = new URL(urlString);
                    URLConnection co =  url.openConnection();
                    co.connect();
                    return "連接可用";
                } catch (Exception e1) {
                    return "連接打不開!";
                }
            }
        }
        
    • order 服務(wù)

      order我們不提供服務(wù)接口,我們只通過user服務(wù)來訪問order服務(wù)所在機(jī)器的ip判斷是否可以連通。

      • 配置文件

        spring:
          cloud:
            nacos:
              discovery:
                #指定nacos server的地址
                server-addr: 101.55.33.23:8848
          application:
            name: order
        
        server:
          port: 9090
        
    • 啟動(dòng)服務(wù)后即可注冊到Nacos

      image.png
+ user服務(wù)地址

  ![image.png](https://upload-images.jianshu.io/upload_images/11383008-5e92e3cfa4cf5fd9.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)


+ order 服務(wù)地址

  ![image.png](https://upload-images.jianshu.io/upload_images/11383008-a15edf4b1e23b76f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
  • 本地測試服務(wù)

    訪問 user 服務(wù),可以正常獲取到 order 服務(wù)的地址信息

    image.png
  • 編寫 2 個(gè)項(xiàng)目的 Dockerfile

    • user 服務(wù)

      FROM openjdk:8-jre-alpine
      COPY user-0.0.1-SNAPSHOT.jar /user.jar
      ENTRYPOINT ["java","-jar","/user.jar"]
      
    • order 服務(wù)

      FROM openjdk:8-jre-alpine
      COPY order-0.0.1-SNAPSHOT.jar /order.jar
      ENTRYPOINT ["java","-jar","/order.jar"]
      
  • 獲取 2 個(gè)項(xiàng)目的 Jar 包與Dockerfile一起上傳服務(wù)器

    [root@master-kubeadm-k8s nacos]# ll
    total 0
    drwxr-xr-x. 2 root root 56 Apr  4 06:05 order
    drwxr-xr-x. 2 root root 55 Apr  4 06:05 user
    
    # order 服務(wù)
    [root@master-kubeadm-k8s nacos]# ll ./order/
    total 32552
    -rw-r--r--. 1 root root      107 Apr  4 06:05 Dockerfile
    -rw-r--r--. 1 root root 33328956 Apr  4 06:04 order-0.0.1-SNAPSHOT.jar
    
    # user 服務(wù)
    [root@master-kubeadm-k8s nacos]# ll ./user/
    total 32556
    -rw-r--r--. 1 root root      104 Apr  4 06:05 Dockerfile
    -rw-r--r--. 1 root root 33330518 Apr  4 06:04 user-0.0.1-SNAPSHOT.jar
    
  • 生成 image 鏡像

    # 生成 user-image
    [root@master-kubeadm-k8s user]# docker build -t user-image .
    Sending build context to Docker daemon  33.33MB
    Step 1/3 : FROM openjdk:8-jre-alpine
     ---> f7a292bbb70c
    Step 2/3 : COPY user-0.0.1-SNAPSHOT.jar /user.jar
     ---> cdcf57ffcd9e
    Step 3/3 : ENTRYPOINT ["java","-jar","/user.jar"]
     ---> Running in fcebef970173
    Removing intermediate container fcebef970173
     ---> c791a8564979
    Successfully built c791a8564979
    Successfully tagged user-image:latest
    
    # 生成 order-image
    [root@master-kubeadm-k8s order]# docker build -t order-image .
    Sending build context to Docker daemon  33.33MB
    Step 1/3 : FROM openjdk:8-jre-alpine
     ---> f7a292bbb70c
    Step 2/3 : COPY order-0.0.1-SNAPSHOT.jar /order.jar
     ---> 60d8a5f1f8d1
    Step 3/3 : ENTRYPOINT ["java","-jar","/order.jar"]
     ---> Running in ca058de2b8a0
    Removing intermediate container ca058de2b8a0
     ---> e27b4f1bfce9
    Successfully built e27b4f1bfce9
    Successfully tagged order-image:latest
    
  • 上傳 image 到鏡像倉庫

    一般K8S要使用鏡像都需要上傳到鏡像倉庫,讓它從網(wǎng)上去下載鏡像,因?yàn)镵8S在創(chuàng)建Pod不是只在固定的節(jié)點(diǎn)創(chuàng)建的,它會(huì)分配到不同的節(jié)點(diǎn)上。

    如果不想將 image 上傳鏡像倉庫,那只能在所有節(jié)點(diǎn)中都創(chuàng)建出 image才行

    # 為 user-image 打 tag
    [root@master-kubeadm-k8s user]# docker tag user-image registry.cn-hangzhou.aliyuncs.com/zhao_yang/user-image:v1.0
    
    # 上傳 user-image 到鏡像倉庫
    [root@master-kubeadm-k8s user]# docker push registry.cn-hangzhou.aliyuncs.com/zhao_yang/user-image:v1.0
    The push refers to repository [registry.cn-hangzhou.aliyuncs.com/zhao_yang/user-image]
    bc5590316af2: Pushed
    edd61588d126: Pushed
    9b9b7f3d56a0: Pushed
    f1b5933fe4b5: Pushed
    v1.0: digest: sha256:837894b2657b7084bdc64ggfddf347afc27ae1a8dfg324bdd238aa108c3464 size: 1159
    
    # 為 order-image 打 tag
    [root@master-kubeadm-k8s user]# docker tag order-image registry.cn-hangzhou.aliyuncs.com/zhao_yang/order-image:v1.0
    
    [root@master-kubeadm-k8s ~]# docker push registry.cn-hangzhou.aliyuncs.com/zhao_yang/order-image:v1.0
    The push refers to repository [registry.cn-hangzhou.aliyuncs.com/zhao_yang/order-image]
    0b5a4e8a7fda: Pushed
    edd61588d126: Pushed
    9b9b7f3d56a0: Pushed
    f1b5933fe4b5: Pushed
    v1.0: digest: sha256:896088772c5f1c187db2645e29fsdghdfg4328c8c94dd783ddfg32ab7618d50 size: 1159
    
  • 編寫 YAML 文件

    • user 服務(wù)

      # 以Deployment部署Pod
      apiVersion: apps/v1
      kind: Deployment
      metadata: 
        name: user
      spec: 
        selector: 
          matchLabels: 
            app: user
        replicas: 1
        template: 
          metadata:
            labels: 
              app: user
          spec: 
            containers: 
            - name: user
              image: registry.cn-hangzhou.aliyuncs.com/zhao_yang/user-image:v1.0
              imagePullPolicy: IfNotPresent
              ports: 
              - containerPort: 8080
      ---
      # 創(chuàng)建Pod的Service
      apiVersion: v1
      kind: Service
      metadata: 
        name: user
      spec: 
        ports: 
        - port: 80
          protocol: TCP
          targetPort: 8080
        selector: 
          app: user
      ---
      # 創(chuàng)建Ingress,定義訪問規(guī)則
      apiVersion: networking.k8s.io/v1beta1
      kind: Ingress
      metadata: 
        name: user
      spec: 
        rules: 
        - host: tomcat.sunny.com
          http: 
            paths: 
            - path: /
              backend: 
                serviceName: user
                servicePort: 80
      
    • order 服務(wù)

      order 服務(wù)無需對(duì)外開放,所以不需要編寫 Ingress 規(guī)則

      # 以Deployment部署Pod
      apiVersion: apps/v1
      kind: Deployment
      metadata: 
        name: order
      spec: 
        selector: 
          matchLabels: 
            app: order
        replicas: 1
        template: 
          metadata:
            labels: 
              app: order
          spec: 
            containers: 
            - name: order
              image: registry.cn-hangzhou.aliyuncs.com/zhao_yang/order-image:v1.0
              imagePullPolicy: IfNotPresent
              ports: 
              - containerPort: 9090
      ---
      # 創(chuàng)建Pod的Service
      apiVersion: v1
      kind: Service
      metadata: 
        name: order
      spec: 
        ports: 
        - port: 80
          protocol: TCP
          targetPort: 9090
        selector: 
          app: order
      
  • 創(chuàng)建資源

    # 創(chuàng)建 user 資源
    [root@master-kubeadm-k8s user]# kubectl apply -f nacos-user.yaml
    deployment.apps/user created
    service/user created
    ingress.networking.k8s.io/user created
    
    # 創(chuàng)建 order 資源
    [root@master-kubeadm-k8s order]# kubectl apply -f nacos-order.yaml
    deployment.apps/order created
    service/order created
    
  • 查看資源

    # 服務(wù)都正常運(yùn)行了
    [root@master-kubeadm-k8s order]# kubectl get pods
    NAME                    READY   STATUS    RESTARTS   AGE
    order-d5f8d8b44-2p4m4   1/1     Running   0          4m30s
    user-54b8fccd67-9925h   1/1     Running   0          7m2s
    
    # 查看 Ingress
    [root@master-kubeadm-k8s order]# kubectl get ingress
    NAME   HOSTS              ADDRESS   PORTS   AGE
    user   tomcat.sunny.com             80      7m52s
    
  • 查看Nacos注冊中心

    服務(wù)正常注冊

    image.png
  • 驗(yàn)證訪問

    測試成功

    image.png

2.3.3 服務(wù)注冊可能存在的坑

現(xiàn)在的情況是 user 與 order 服務(wù)都部署在集群內(nèi),通信是肯定沒問題的。

如果 user 服務(wù)是運(yùn)行在外部的,以現(xiàn)在的配置,user 服務(wù)肯定是無法訪問到 集群內(nèi)的 order 服務(wù)的,因?yàn)樗麄冏缘?Nacos 的 IP 不是在同一個(gè)網(wǎng)段的,所以肯定無法連通!

  • user

    image.png
  • order

    image.png
  • 測試

    image.png
  • 解決辦法

    因?yàn)?order 服務(wù)注冊到 Nacos 的IP是用于集群內(nèi)通信的,那我們只要想辦法把這個(gè)IP換掉,換成外部服務(wù)可以 ping 通的 IP 不就可以了?

    以我們現(xiàn)在學(xué)習(xí)過的網(wǎng)絡(luò)知識(shí),我們知道外部服務(wù)要訪問集群內(nèi)的服務(wù),目前有兩種方式:

    • NodePort
    • HostPort

    由于NodePort會(huì)在集群內(nèi)所有節(jié)點(diǎn)都開放一個(gè)端口,所以我們不推薦使用。

    而 HostPort 僅僅是在Pod所在節(jié)點(diǎn)開放端口,其實(shí) HostPort 就是 Docker 中的 Host 網(wǎng)絡(luò)模式,它是共享宿主機(jī)的 IP 與 端口的。這種方式也是現(xiàn)在比較推薦的做法!

    使用HostPort網(wǎng)絡(luò)模式的情況下,如果服務(wù)高可用會(huì)有端口沖突問題

    可以使用 Pod 的調(diào)度策略,盡可能在高可用的情況下,不將pod分配到同一個(gè)Worker Node中

  • 修改 order 服務(wù)的 YAML 文件

    # 以Deployment部署Pod
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: order
    spec:
      selector:
        matchLabels:
          app: order
      replicas: 1
      template:
        metadata:
          labels:
            app: order
        spec:
          # ============修改為HostPort模式=============
          hostNetwork: true
          # ============修改為HostPort模式=============
          containers:
          - name: order
            image: registry.cn-hangzhou.aliyuncs.com/zhao_yang/order-image:v1.0
            imagePullPolicy: IfNotPresent
            ports:
            - containerPort: 9090
    ---
    # 創(chuàng)建Pod的Service
    apiVersion: v1
    kind: Service
    metadata:
      name: order
    spec:
      ports:
      - port: 80
        protocol: TCP
        targetPort: 9090
      selector:
        app: order
    
  • 重新創(chuàng)建資源并查看 Nacos 中 order 服務(wù)的地址信息

image.png

結(jié)果發(fā)現(xiàn)這并不是我想要的IP,我們檢查一下這個(gè)容器使用的網(wǎng)卡信息。

image.png

從這里發(fā)現(xiàn)原因,它是把 eth0 網(wǎng)卡的IP注冊上去了,這個(gè)IP是沒法通過外部來訪問的,我們要修改讓它使用 eth1 網(wǎng)卡才行。

  • Nacos解決方案

    • 通過查看文檔,可以選擇配置不同的網(wǎng)卡或者IP

      (參考o(jì)rg.springframework.cloud.alibaba.nacos.NacosDiscoveryProperties的配置)

    • 選擇固定網(wǎng)卡配置項(xiàng)

      • 在 order 項(xiàng)目的配置文件中增加配置

        spring:
          cloud:
            nacos:
              discovery:
                #指定nacos server的地址
                server-addr: 101.111.45.23:8848
                # 指定網(wǎng)卡配置項(xiàng)
                network-interface: eth1
          application:
            name: order
        
        server:
          port: 9090
        
    • 重新生成 Jar、image,重新創(chuàng)建資源

    • 查看Nacos中 order 服務(wù)的地址信息

      image.png

現(xiàn)在這個(gè)IP是我們想要的了

  • 測試

    image.png
至此,三個(gè)案例就都演示完成了!中間也是遇到了不少坑,花了不少時(shí)間解決錯(cuò)誤,希望這個(gè)筆記也能幫到大家少碰到一些坑吧?。?/h5>
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容