[kubernetes] K8S deployment SpringBoot project

Build image

  1. Original deployment method:

    Type the java application into a jar package, and then use the java command to start the application

    java -jar springBootAdmin-0.0.1-SNAPSHOT.jar
    
  2. Existing problems: the server needs to have the corresponding version of java environment and mysql environment installed

  3. resolvent:

    1. Container deployment
    2. Docker is installed on all machines, any application is a mirror, and all machines can run
  4. Create a SpringBoot program

    @RestController
    public class testController {
        private int count = 0;
        @RequestMapping("/test")
        public String test(){
            return "Yes["+ count++ +"] People visited this page";
        }
    }
    
  5. Write Dockerfile

    FROM openjdk:8-jdk-slim
    
    COPY target/*.jar /app.jar
    ENTRYPOINT ["java","-jar","app.jar"]
    

    Go to DockerHub to find the image you want


    There was a little doubt before: why is there only JDK here instead of maven?

    • maven doesn't need to be written in Dockerfile. It should be maven. Its function here is a packaging tool
    • In the process of making jar packages for windows, the required files have been downloaded and typed into the jar package, so maven is not required in the project deployment environment
    • Think about it carefully. It's really not necessary
    • However, it is not clear how to match the containers running mysql and redis that need to be called in complex projects
  6. Package with maven, and only keep Dockerfile and jar package dockersprinbootdemo-0.0.1-snapshot jar

  7. To the server:

    [root@master DockerSpringBootDemo]# ls
    Dockerfile  target
    
    [root@master DockerSpringBootDemo]# cd target/
    
    [root@master target]# ls
    dockerSpringBootDemo-0.0.1-SNAPSHOT.jar
    
    [root@master target]# cd ..
    [root@master DockerSpringBootDemo]# pwd
    /root/springBootDemo/DockerSpringBootDemo
    
  8. Build image

    [root@master DockerSpringBootDemo]# docker build -t srping_boot_demo:v1.0 .
    Sending build context to Docker daemon  17.56MB
    Step 1/3 : FROM openjdk:8-jdk-slim
    8-jdk-slim: Pulling from library/openjdk
    a2abf6c4d29d: Pull complete 
    2bbde5250315: Pull complete 
    115191490c27: Pull complete 
    61b680ac8083: Pull complete 
    Digest: sha256:25efb6e0609b95af243b4e3ce2c27dbc1022ef2a4db2164b7afa066c0db18137
    Status: Downloaded newer image for openjdk:8-jdk-slim
     ---> 9afd0fe33df7
    Step 2/3 : COPY target/*.jar /app.jar
     ---> 37304d0eb2ec
    Step 3/3 : ENTRYPOINT ["java","-jar","app.jar"]
     ---> Running in 549652c11e1d
    Removing intermediate container 549652c11e1d
     ---> 0d2fd9fd3003
    Successfully built 0d2fd9fd3003
    Successfully tagged srping_boot_demo:v1.0
    

    The name of the image cannot contain uppercase letters!

    [root@master DockerSpringBootDemo]# docker build -t srpingBootDemo:v1.0 .
    invalid argument "srpingBootDemo:v1.0" for "-t, --tag" flag: invalid reference format: repository name must be lowercase
    See 'docker build --help'.
    
  9. View mirror

    [root@master DockerSpringBootDemo]# docker images
    REPOSITORY                                              TAG          IMAGE ID       CREATED          SIZE
    srping_boot_demo                                        v1.0         0d2fd9fd3003   11 seconds ago   313MB
    
  10. Start the container (the purpose of starting the container here is to test whether the image is normal)

    [root@master DockerSpringBootDemo]# docker run -d -p 8080:8080 srping_boot_demo:v1.0
    e50243abeadc4ab1f51edc7929db3296774d2a5ee8369d9d52fc557c53cecd49
    
  11. View container

    [root@master DockerSpringBootDemo]# docker ps
    CONTAINER ID   IMAGE                                               COMMAND                  CREATED         STATUS         PORTS                                       NAMES
    e50243abeadc   srping_boot_demo:v1.0                               "java -jar app.jar"      7 seconds ago   Up 6 seconds   0.0.0.0:8080->8080/tcp, :::8080->8080/tcp   kind_yalow
    
  12. http://192.168.10.171:8080/test
    Visit successful

Build image warehouse

Create a new machine:

[root@registry ~]# cat /etc/sysconfig/network-scripts/ifcfg-ens32 
TYPE="Ethernet"
PROXY_METHOD="none"
BROWSER_ONLY="no"
BOOTPROTO="static"
DEFROUTE="yes"
IPV4_FAILURE_FATAL="no"
IPV6INIT="yes"
IPV6_AUTOCONF="yes"
IPV6_DEFROUTE="yes"
IPV6_FAILURE_FATAL="no"
IPV6_ADDR_GEN_MODE="stable-privacy"
NAME="ens32"
UUID="9be4c57a-42b1-4fdb-b940-b1b6770e9a20"
DEVICE="ens32"
ONBOOT="yes"
IPADDR=192.168.10.174
GATEWAY=192.168.10.2
DNS1=192.168.10.2

[root@registry ~]# cat /etc/hostname 
registry

[root@registry ~]# cat /etc/hosts
192.168.10.171 master
192.168.10.174 registry

Operate on the local mirror server

  1. Install Docker

    1. Install wget

      yum install wget
      
    2. Install Docker

      wget https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo -O /etc/yum.repos.d/docker-ce.repo
      
      yum -y install docker-ce-18.06.1.ce-3.el7
      
      systemctl enable docker && systemctl start docker
      
      docker --version
      
    3. Configure Alibaba cloud acceleration for Docker

      cat > /etc/docker/daemon.json << EOF
      {
      "registry-mirrors": ["https://b9pmyelo.mirror.aliyuncs.com"]
      } 
      EOF
      
    4. Restart docker service

      systemctl daemon-reload
      
      systemctl restart docker
      
    5. Verify whether the Alibaba cloud warehouse is successfully configured

      docker info
      
      ...
      Registry Mirrors:
       https://b9pmyelo.mirror.aliyuncs.com/
      ...
      
  2. pull is an official template image of the registry, which is used to build the warehouse on the image warehouse server

    [root@registry ~]# docker run -d -v /opt/registry:/var/lib/registry -p 5000:5000 --restart=always registry
    

Modify mirror source

Operate on the master node, node01 node and node02 node of K8S cluster

  1. Modify the port configuration file and change the above Alibaba cloud warehouse into a self built local image warehouse

    [root@registry ~]# vim /etc/docker/daemon.json
    
    {	
            "insecure-registries": ["192.168.10.110:5000"]
    }
    

    Note here: Secure registers

  2. Restart docker

    [root@registry ~]# systemctl daemon-reload
    [root@registry ~]# systemctl restart docker
    
  3. View the Docker image warehouse used at this time

    [root@registry ~]# docker info
    
    ...
    Insecure Registries:
     192.168.10.174:5000
     127.0.0.0/8
    ...
    

Remember to modify all node nodes in the cluster to the image warehouse source!

The image is pulled after the Pod scheduling, that is, the node node is the real image. Stepping on the pit: because only the image warehouse source of the master node is changed, the image download will fail all the time

[root@master DockerSpringBootDemo]# kubectl get pod
NAME             READY   STATUS              RESTARTS   AGE
springbootdemo   0/1     ContainerCreating   0          5s

[root@master DockerSpringBootDemo]# kubectl describe pod springbootdemo
...
Events:
  Type     Reason     Age                  From               Message
  ----     ------     ----                 ----               -------
  Normal   Scheduled  2m38s                default-scheduler  Successfully assigned default/springbootdemo to node02		# ⭐  The pod is dispatched to node02, which starts downloading the image
  Warning  Failed     63s (x2 over 114s)   kubelet            Failed to pull image "springbootdemo:v1.0": rpc error: code = Unknown desc = Error response from daemon: pull access denied for springbootdemo, repository does not exist or may require 'docker login': denied: requested access to the resource is denied
  Warning  Failed     63s (x2 over 114s)   kubelet            Error: ErrImagePull
  Normal   BackOff    49s (x2 over 114s)   kubelet            Back-off pulling image "springbootdemo:v1.0"
  Warning  Failed     49s (x2 over 114s)   kubelet            Error: ImagePullBackOff
  Normal   Pulling    34s (x3 over 2m37s)  kubelet            Pulling image "springbootdemo:v1.0"

Push image

Operate on the master node of the K8S cluster

  1. push image to local image warehouse

    1. Modify the name of the image to upload:

      Image identifier required for uploading image: warehouse address / userName/imageName:tag

      [root@master DockerSpringBootDemo]# docker tag springbootdemo:v1.0 192.168.10.174:5000/springbootdemo:v1.0
      
    2. push image

      [root@master DockerSpringBootDemo]# docker push 192.168.10.174:5000/springbootdemo:v1.0
      The push refers to repository [192.168.10.174:5000/springbootdemo]
      773f14f8f38a: Pushed 
      c8fa2e981776: Pushed 
      3341e899db61: Pushed 
      afda989d53ee: Pushed 
      2edcec3590a4: Pushed 
      v1.0: digest: sha256:0a9303110e485a3ac6bcd9e21e07124eaea97b05447204b05ceaf8e8f53c28dc size: 1372
      
    3. View images on the local image repository

      [root@master DockerSpringBootDemo]# curl -XGET http://192.168.10.174:5000/v2/_catalog
      {"repositories":["springbootdemo"]}
      
  2. Test whether the image on the local self built image warehouse is available

    1. Boot container using remote mirror

      [root@master DockerSpringBootDemo]# docker run --name springbootdemo -p 8080:8080 192.168.10.174:5000/springbootdemo:v1.0
      Unable to find image '192.168.10.174:5000/springbootdemo:v1.0' locally		# Mirror not found locally
      v1.0: Pulling from springbootdemo											# Go to the self built image warehouse to download
      a2abf6c4d29d: Already exists 
      2bbde5250315: Already exists 
      115191490c27: Already exists 
      61b680ac8083: Already exists 
      587148c8979a: Already exists 
      Digest: sha256:0a9303110e485a3ac6bcd9e21e07124eaea97b05447204b05ceaf8e8f53c28dc
      Status: Downloaded newer image for 192.168.10.174:5000/springbootdemo:v1.0
      

    2. visit: http://192.168.10.171:8080/test

      Run successfully

Start Pod with deployment

  1. Get yaml file template using command

    [root@master ~]# kubectl create deployment springbootdemo --image=192.168.10.174:5000/springbootdemo:v1.0 --dry-run=client -o yaml > springbootdemo.yaml
    
    [root@master ~]# ls
    ... springbootdemo.yaml ...
    
    [root@master ~]# vi springbootdemo.yaml
    
  2. Make requirement modification to yaml configuration

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      creationTimestamp: null
      labels:
        app: springbootdemo
      name: springbootdemo
    spec:
      replicas: 3			# Start three highly available services
      selector:
        matchLabels:
          app: springbootdemo
      strategy: {}
      template:
        metadata:
          creationTimestamp: null
          labels:
            app: springbootdemo
        spec:
          containers:
          - image: 192.168.10.174:5000/springbootdemo:v1.0		# Image of local self built image warehouse
            name: springbootdemo
            resources: {}
    status: {}
    
  3. Start deployment

    [root@master ~]# kubectl create -f springbootdemo.yaml 
    deployment.apps/springbootdemo created
    
  4. View deployment

    [root@master ~]# kubectl get deployment
    NAME             READY   UP-TO-DATE   AVAILABLE   AGE
    springbootdemo   3/3     3            3           13s
    
  5. Production view pod

    [root@master ~]# kubectl get pod
    NAME                              READY   STATUS    RESTARTS   AGE
    springbootdemo-75f458f7fc-65c64   1/1     Running   0          21s
    springbootdemo-75f458f7fc-9n6r7   1/1     Running   0          21s
    springbootdemo-75f458f7fc-djgjf   1/1     Running   0          21s
    

Expose ports using NodePort

  1. Create service yaml file

    apiVersion: v1
    kind: Service
    metadata:
      name: springbootdemo-service
    spec:
      selector:
        app: springbootdemo		# ⭐  The tag selector must be written here, otherwise the service does not know which deployment to expose the port to! And corresponding to the label of deploy
      type: NodePort			# The sevice type is nodeport
      ports:
      - port: 8080				# service port
        nodePort: 30000			# Port of node
        targetPort: 8080		# Port of the application (already written in the code)
    

    The designation of nodePort is required by the scope:

    The Service "service-nodeport" is invalid: spec.ports[0].nodePort: Invalid value: 3000: provided port is not in the valid range. The range of valid ports is 30000-32767
    
  2. Create a service to expose external services to deployment

    [root@master ~]# kubectl create -f springbootdemoservice.yaml
    service/springbootdemo-service created
    
  3. View service

    [root@master ~]# kubectl get svc -o wide
    NAME                     TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE   SELECTOR
    kubernetes               ClusterIP   10.96.0.1        <none>        443/TCP          11d   <none>
    springbootdemo-service   NodePort    10.100.146.163   <none>        8080:30000/TCP   4s    app=springbootdemo
    
  4. You can also use the expose command to expose the service directly

    [root@master ~]# kubectl expose deployment springbootdemo --port=8080 --type=NodePort
    service/nginx exposed
    

Test access

visit: http://192.168.10.171:30000/test

Tags: Docker Kubernetes Operation & Maintenance Spring Boot

Posted by Jeremysr on Tue, 19 Apr 2022 11:06:25 +0930