美文网首页Kubernetes
五、Kubernetes 实战项目搭建

五、Kubernetes 实战项目搭建

作者: Suny____ | 来源:发表于2020-04-03 16:48 被阅读0次

1、步骤梳理

本章节将主要围绕实战搭建项目为主,既然是实战,就得考虑好需要准备哪些东西,所有的准备都做好了,才能正确的往下进行。本章节目的在于把之前学习的知识点进行一次串联,加深一下映像!

本次实战准备了三个案例:

  • WordPress + MySQL
  • Spring Boot项目
  • Nacos服务注册与发现

每个案例都会以不同的通信方式去部署。

1.1、服务搭建步骤

  • 确定自己当前的服务有哪些
  • 服务是官方的还是自定义的
    • 若是自定义则需要编写Dockerfile
    • 自定义的镜像上传镜像仓库 【可选】
  • 服务隔离【可选】
    • 服务很多的情况下,为了方便管理,一般会创建一个独立的命名空间为这个项目使用
  • 创建服务所需的 YAML 文件
  • 服务发现的策略
    • 通过 Service NodePort实现集群内部通信
    • 通过 Ingress 实现集群内外通信
  • 服务监控、日志收集等 【暂不实现】
    • 本章不演示,因为目前还没有开始学习到这部分,等到后面再慢慢分享!

2、项目搭建

2.1、WordPress + MySQL

2.1.1 搭建说明

  • 2个服务都使用官方 image,所以无需编写Dockerfile
  • 创建命名空间
  • 编写 YAML 文件
    • mysql 服务我们只给wordpress访问,所以直接用 ClusterIP方式实现集群内通信即可。
    • wordpress 服务需要外部访问,使用NodePort方式进行通信。

2.1.2 服务搭建

  • 创建 WordPress 命名空间

    [root@master-kubeadm-k8s wordpress]# kubectl create namespace wordpress
    namespace/wordpress created
    
  • 创建 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                 # 这里增加 节点选择器 , 前面章节我们为 worker01 节点创建了 name: ingress 标签,这里用一下
          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                  # 创建一个数据库 名为 wordpress
              value: wordpress
            - name: MYSQL_USER                              # wordpress数据库的用户名
              value: wordpress
            - name: MYSQL_PASSWORD                  # wordpress数据库的密码
              value: wordpress
            volumeMounts:                                   # 指定容器的映射目录
            - name: db
              mountPath: /var/lib/mysql
          volumes:                                                  # 指定宿主机的映射目录
          - 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
    
  • 创建 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         # 指定数据库ip:port
              value: 10.104.83.208:3306        # 这里用mysql的service的ip、名称或pod的ip都可以
            - name: WORDPRESS_DB_USER         # 指定数据库用户名
              value: wordpress
            - name: WORDPRESS_DB_PASSWORD     # 指定数据库密码
              value: wordpress
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: wordpress
      namespace: wordpress
    spec:
      type: NodePort                          # 指定 Service 网络模式
      selector:
        app: wordpress
      ports:
      - name: wordpressport
        protocol: TCP
        port: 80
        targetPort: wdport
    
  • 创建资源

    # 创建 wordpress-db
    [root@master-kubeadm-k8s wordpress]# kubectl apply -f wordpress-db.yaml
    deployment.apps/mysql-deploy created
    service/mysql created
    
    # 创建 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
    
  • 测试

    访问宿主机 ip:32731

    image.png

若出现访问不通的情况, 可以在宿主机执行 iptables -P FORWARD ACCEPT 命令就可以解决

2.2、Spring Boot 项目部署

2.2.1 搭建说明

  • 准备服务,生成 Jar 文件并上传服务器
  • 服务是自己的项目代码,需要编写Dockerfile
  • 镜像上传镜像仓库
  • 编写 YAML 文件
    • 为了供外部访问,采用 Ingress controller方式进行通信

2.2.2 服务搭建

  • 准备服务

    image.png
  • 准备 Jar 包并上传至服务器

  • 编写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
    ---
    # 创建Pod的Service
    apiVersion: v1
    kind: Service
    metadata: 
      name: springboot-demo
    spec: 
      ports: 
      - port: 80
        protocol: TCP
        targetPort: 8080
      selector: 
        app: springboot-demo
    ---
    # 创建Ingress,定义访问规则,一定要记得提前创建好nginx ingress controller
    apiVersion: networking.k8s.io/v1beta1
    kind: Ingress
    metadata: 
      name: springboot-demo
    spec: 
      rules: 
      - host: tomcat.sunny.com    # windows hosts中配置了与宿主机ip对应的域名
        http: 
          paths: 
          - path: /
            backend: 
              serviceName: springboot-demo
              servicePort: 80
    

    因为在之前的章节演示中,我们已经创建好了 Ingress Controller,所以这里直接写 Ingress规则即可

  • 创建资源

    # 创建资源
    [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, 发现还没创建好
    [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 描述, 看当前在做什么
    [root@master-kubeadm-k8s k8s-springboot-demo]# kubectl describe pod springboot-demo-5f6f5c9696-5gj9k
    # ...省略...
    
    # ===================== 发现拉取镜像失败了 ======================
    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
    

    其实这是权限问题,K8S需要有一个认证才能从私有仓库拉取镜像,可以创建 Secret 解决

    如果是公开库就可以正常拉取,不会出现这种问题

    • 解决K8S拉取不了私有镜像仓库的问题

       # 在集群中创建保存授权令牌的 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认证

        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   # 注意名称要与创建时指定的名称一致
                #=========增加 Secret===========
        ---
        # 创建Pod的Service
        apiVersion: v1
        kind: Service
        metadata: 
          name: springboot-demo
        spec: 
          ports: 
          - port: 80
            protocol: TCP
            targetPort: 8080
          selector: 
            app: springboot-demo
        ---
        # 创建Ingress,定义访问规则,一定要记得提前创建好nginx ingress controller
        apiVersion: networking.k8s.io/v1beta1
        kind: Ingress
        metadata: 
          name: springboot-demo
        spec: 
          rules: 
          - host: tomcat.sunny.com    # windows hosts中配置了与宿主机ip对应的域名
            http: 
              paths: 
              - path: /
                backend: 
                  serviceName: springboot-demo
                  servicePort: 80
        
    • 重新创建资源

      # 创建资源
      [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
      
      # 已经创建完成
      [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 服务

2.3、Nacos 服务注册与发行

2.3.1 搭建说明

  • 准备Nacos注册中心
  • 准备两个服务,一个服务依赖另一个服务
    • user、order服务
  • 服务注册至 Nacos
  • 编写两个服务的Dockerfile
  • 编写 YAML 文件
    • Nacos注册中心这里不通过容器部署,所以就不写 YAML 文件了

2.3.2 服务搭建

  • 准备 Nacos 注册中心

    注册中心的选择是自定义的,这里只是选择了Nacos作为演示,你也可以选择其他的注册中心去测试!

    以单机模式启动 nacos

    image.png

访问物理机 ip:8848/nacos 即可访问注册中心

nacos 默认的用户名:nacos,密码:nacos

image.png
  • 准备user、order项目并验证
    • POM 依赖

      注意:Cloud生态对版本依赖还是挺大的,如果SpringBoot版本与SpringCloud版本不匹配可能会出现问题的

      <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 服务

      • 配置文件

        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 来发现服务
             */
            @RequestMapping("/test")
            public Map<String, Object> findServiceInstance() throws Exception{
                //查询指定服务名称下的所有实例的信息
                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 服务的结果
                map.put("testResult", testResult);
        
                return map;
            }
        
            /**
             * 测试user服务能否 ping 通order服务的ip
             *
             * @param urlString order服务所在机器的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 服务

      order我们不提供服务接口,我们只通过user服务来访问order服务所在机器的ip判断是否可以连通。

      • 配置文件

        spring:
          cloud:
            nacos:
              discovery:
                #指定nacos server的地址
                server-addr: 101.55.33.23:8848
          application:
            name: order
        
        server:
          port: 9090
        
    • 启动服务后即可注册到Nacos

      image.png
+ user服务地址

  ![image.png](https://img.haomeiwen.com/i11383008/5e92e3cfa4cf5fd9.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)


+ order 服务地址

  ![image.png](https://img.haomeiwen.com/i11383008/a15edf4b1e23b76f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
  • 本地测试服务

    访问 user 服务,可以正常获取到 order 服务的地址信息

    image.png
  • 编写 2 个项目的 Dockerfile

    • user 服务

      FROM openjdk:8-jre-alpine
      COPY user-0.0.1-SNAPSHOT.jar /user.jar
      ENTRYPOINT ["java","-jar","/user.jar"]
      
    • order 服务

      FROM openjdk:8-jre-alpine
      COPY order-0.0.1-SNAPSHOT.jar /order.jar
      ENTRYPOINT ["java","-jar","/order.jar"]
      
  • 获取 2 个项目的 Jar 包与Dockerfile一起上传服务器

    [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 服务
    [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 服务
    [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要使用镜像都需要上传到镜像仓库,让它从网上去下载镜像,因为K8S在创建Pod不是只在固定的节点创建的,它会分配到不同的节点上。

    如果不想将 image 上传镜像仓库,那只能在所有节点中都创建出 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 服务

      # 以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
      ---
      # 创建Pod的Service
      apiVersion: v1
      kind: Service
      metadata: 
        name: user
      spec: 
        ports: 
        - port: 80
          protocol: TCP
          targetPort: 8080
        selector: 
          app: user
      ---
      # 创建Ingress,定义访问规则
      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 服务

      order 服务无需对外开放,所以不需要编写 Ingress 规则

      # 以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
      ---
      # 创建Pod的Service
      apiVersion: v1
      kind: Service
      metadata: 
        name: order
      spec: 
        ports: 
        - port: 80
          protocol: TCP
          targetPort: 9090
        selector: 
          app: order
      
  • 创建资源

    # 创建 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
    
    # 创建 order 资源
    [root@master-kubeadm-k8s order]# kubectl apply -f nacos-order.yaml
    deployment.apps/order created
    service/order created
    
  • 查看资源

    # 服务都正常运行了
    [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注册中心

    服务正常注册

    image.png
  • 验证访问

    测试成功

    image.png

2.3.3 服务注册可能存在的坑

现在的情况是 user 与 order 服务都部署在集群内,通信是肯定没问题的。

如果 user 服务是运行在外部的,以现在的配置,user 服务肯定是无法访问到 集群内的 order 服务的,因为他们注册到 Nacos 的 IP 不是在同一个网段的,所以肯定无法连通!

  • user

    image.png
  • order

    image.png
  • 测试

    image.png
  • 解决办法

    因为 order 服务注册到 Nacos 的IP是用于集群内通信的,那我们只要想办法把这个IP换掉,换成外部服务可以 ping 通的 IP 不就可以了?

    以我们现在学习过的网络知识,我们知道外部服务要访问集群内的服务,目前有两种方式:

    • NodePort
    • HostPort

    由于NodePort会在集群内所有节点都开放一个端口,所以我们不推荐使用。

    而 HostPort 仅仅是在Pod所在节点开放端口,其实 HostPort 就是 Docker 中的 Host 网络模式,它是共享宿主机的 IP 与 端口的。这种方式也是现在比较推荐的做法!

    使用HostPort网络模式的情况下,如果服务高可用会有端口冲突问题

    可以使用 Pod 的调度策略,尽可能在高可用的情况下,不将pod分配到同一个Worker Node中

  • 修改 order 服务的 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
    ---
    # 创建Pod的Service
    apiVersion: v1
    kind: Service
    metadata:
      name: order
    spec:
      ports:
      - port: 80
        protocol: TCP
        targetPort: 9090
      selector:
        app: order
    
  • 重新创建资源并查看 Nacos 中 order 服务的地址信息

image.png

结果发现这并不是我想要的IP,我们检查一下这个容器使用的网卡信息。

image.png

从这里发现原因,它是把 eth0 网卡的IP注册上去了,这个IP是没法通过外部来访问的,我们要修改让它使用 eth1 网卡才行。

  • Nacos解决方案

    • 通过查看文档,可以选择配置不同的网卡或者IP

      (参考org.springframework.cloud.alibaba.nacos.NacosDiscoveryProperties的配置)

    • 选择固定网卡配置项

      • 在 order 项目的配置文件中增加配置

        spring:
          cloud:
            nacos:
              discovery:
                #指定nacos server的地址
                server-addr: 101.111.45.23:8848
                # 指定网卡配置项
                network-interface: eth1
          application:
            name: order
        
        server:
          port: 9090
        
    • 重新生成 Jar、image,重新创建资源

    • 查看Nacos中 order 服务的地址信息

      image.png

现在这个IP是我们想要的了

  • 测试

    image.png
至此,三个案例就都演示完成了!中间也是遇到了不少坑,花了不少时间解决错误,希望这个笔记也能帮到大家少碰到一些坑吧!!

相关文章

网友评论

    本文标题:五、Kubernetes 实战项目搭建

    本文链接:https://www.haomeiwen.com/subject/czmjphtx.html