Orange Pi 4 and Raspberry Pi 4B build K8S cluster practice six: App service deployment

Directory

1. Description

1.1 Regarding the WebApp of the PHP + Nginx system, two deployment modes will be practiced here:

1.2 Configuration list

2. WebApp deployment of PHP + Nginx system

2.1 Single-node multi-container mode A

2.1.1 Preparations

2.2.2 Deployment

2.2.3 Access Effect

2.2 Multi-node single container mode B

2.2.1 Preparations

2.2 Configure virtual host

3. Java Springboot App deployment

3.1 Create a springboot-hello project in VS Code

3.2 Create an App image

3.3 deployment

4. Session session keeps setting

5. Problems encountered

6. Reference


1. Description

– According to the previous k8s foundation, I plan to set up two different virtual hosts to run on this K8s cluster, one is the WebApp of the PHP + Nginx system, and the other is the WebApp of the Java SpringBoot system.

1.1 Regarding the WebApp of the PHP + Nginx system, two deployment modes will be implemented here:

  • Single-node multi-container mode A – is a cross-container design mode, the purpose is to run multiple containers (processes) with super-intimate relationships on a single host, so the container management system needs to treat it as an atom The unit conducts unified scheduling. The Pod concept designed by the Kubernetes orchestration system is one of the implementations of this design pattern.
  • Multi-node single-container collaboration mode B – Distribute each instance of a distributed application (eg: nginx, php, mariadb…) to multiple nodes and run in single-node mode

1.2 Configuration List

– wwwroot is the file directory where pvc was defined before, in the form of: /data0/nfs/iot-age-wwwroot-pvc-202ba85a-fd3f-4817-98ea-6764f9ec0d55

< /table>

2. WebApp deployment of PHP + Nginx system

2.1 Single-node multi-container mode A

2.1.1 Preparations

Using the well-known phpmyadmin as a demonstration app, first package it into a mirror with the buildkit tool, and upload it to hub.docker.com (this is my mirror linkhttps://hub.docker.com/repository/ docker/bennybi/phpmyadmin/general) .

buildctl build \
    --frontend=dockerfile.v0 \
    --local context=.\
    --local dockerfile=.\
    --export-cache type=inline \
    --output type=image,name=docker.io/bennybi/phpmyadmin:v1,push=true

Dockerfile

# This Dockerfile uses the latest version of the Bitnami PHP-FPM Docker image
FROM alpine:latest

# Copy app's source code to the /app directory
COPY ./app

# The application's directory will be the working directory
WORKDIR /app

2.2.2 Deployment

According to the idea of mode A, mode A is used to quickly and conveniently deploy a single application, so I unified the relevant settings into the definition in the phpmyadmin.k8s-t2.com.yaml file, where the rules:

  • The project name or domain needs to replace “.” with “-” to switch to the deployment name, such as phpmyadmin.k8s-t2.com => phpmyadmin-k8s-t2-com
  • In the container, use the image just uploaded as initContainer to deploy the code
  • nginx, php-fpm serves the container, nginx calls local-php-fpm:9000 to explain the php runtime logic
  • When packaging, you need to pre-define the connection to the database service in the code, such as: my-release-mariadb-galera.default, no additional configmap is made here
# Service
apiVersion: v1
kind: Service
metadata:
  name: phpmyadmin-k8s-t2-com
  namespace: iot-age
spec:
  type: ClusterIP
  sessionAffinity: ClientIP
  sessionAffinityConfig:
    clientIP:
      timeoutSeconds: 10800
  ports:
  -name: nginx
    port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: phpmyadmin-k8s-t2-com

---
# deployment
apiVersion: apps/v1
kind: Deployment
metadata:
  name: phpmyadmin-k8s-t2-com
  namespace: iot-age
spec:
  replicas: 2
  selector:
    matchLabels:
      app: phpmyadmin-k8s-t2-com
  template:
    metadata:
      labels:
        app: phpmyadmin-k8s-t2-com
    spec:
      hostAliases:
      - ip: "127.0.0.1"
        hostnames:
        - "local-php-fpm"
      # Private docker mirror warehouse
      # imagePullSecrets:
      # - name: registrykey-qlcoud-1
      # Customize the hosts of the POD
      initContainers:
      - name: app-php
        image: "bennybi/phpmyadmin:v1"
        imagePullPolicy: Always
        # Copy the php program file to wwwroot volume
        command: ["sh", "-c", "cp -r /app /appdata"]
        volumeMounts:
        - mountPath: /appdata
          name: wwwroot
      containers:
      #php-fpm php operating environment
      - name: php-fpm
        image: "bennybi/php-fpm:v1"
        imagePullPolicy: IfNotPresent
        volumeMounts:
        - mountPath: /var/www
          name: wwwroot
      #webserver
      -name: nginx
        image: nginx
        imagePullPolicy: IfNotPresent
        resources: {}
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
        ports:
        - containerPort: 80
        volumeMounts:
        - name: wwwroot
          mountPath: /var/www
        - name: nginx-conf
          mountPath: /etc/nginx/conf.d/
      # Make an emptyDir type volume named wwwroot for multiple containers to share the same mount
      volumes:
      - name: wwwroot
        emptyDir: {}
      - name: nginx-conf
        configMap:
          name: phpmyadmin-k8s-t2-com.nginx-conf
          
---
kind: ConfigMap
apiVersion: v1
metadata:
  name: phpmyadmin-k8s-t2-com.nginx-conf
  namespace: iot-age
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: >
      {"apiVersion":"v1","data":{"default.conf":"server {\\
 listen
      80;\\
 listen [::]:80;\\
 server_name localhost;\\
 \\
 index
      index.php index.html;\\
 error_log /var/log/nginx/error.log;\\

      access_log /var/log/nginx/access.log;\\
 root /var/www/html;\\

      location / {\\
 try_files $uri $uri/ /index.php?$query_string;\\

      }\\
\\
 #location / {\\
 # #root /usr/share/nginx/html;\\
 #
      root /var/www/html;\\
 # index index.php index.html
      index.htm;\\
 #}\\
 \\
 location ~ \.php$ {\\
 try_files $uri
      =404;\\
 fastcgi_split_path_info ^(. + \.php)(/. + )$;\\

      fastcgi_pass local-php-fpm:9000;\\
 fastcgi_index index.php;\\

      include fastcgi_params;\\
 fastcgi_param SCRIPT_FILENAME
      $document_root$fastcgi_script_name;\\
 fastcgi_param PATH_INFO
      $fastcgi_path_info;\\
 }\\
\\
 error_page 500 502 503 504
      /50x.html;\\
 location = /50x.html {\\
 root
      /usr/share/nginx/html;\\

      }\\
}\\
"},"kind":"ConfigMap","metadata":{"annotations":{},"name":"phpmyadmin- k8s-t2-com.nginx-conf","namespace":"iot-age"}}
data:
  default.conf: |
    server {
        listen 80;
        listen [::]:80;
        server_name localhost;
        
        index index.php index.html;
        error_log /var/log/nginx/error.log;
        access_log /var/log/nginx/access.log;
        root /var/www/app;
        location / {
            try_files $uri $uri/ /index.php?$query_string;
        }

        #location /{
        # #root /usr/share/nginx/html;
        # root /var/www/html;
        # index index.php index.html index.htm;
        #}
        
        location ~ \.php$ {
            try_files $uri =404;
            fastcgi_split_path_info ^(. + \.php)(/. + )$;
            fastcgi_pass local-php-fpm:9000;
            fastcgi_index index.php;
            include fastcgi_params;
            fastcgi_param SCRIPT_FILENAME $document_root $fastcgi_script_name;
            fastcgi_param PATH_INFO $fastcgi_path_info;
        }

        error_page 500 502 503 504 /50x.html;
        location = /50x.html {
            root /usr/share/nginx/html;
        }
    }
    
---
#Ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: phpmyadmin-k8s-t2-com
  namespace: iot-age
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/affinity: cookie
    nginx.ingress.kubernetes.io/session-cookie-name: stickounet
    nginx.ingress.kubernetes.io/session-cookie-expires: "172800"
    nginx.ingress.kubernetes.io/session-cookie-max-age: "172800"
spec:
  rules:
    - host: phpmyadmin.k8s-t2.com
      http:
        paths:
        - path: /
          pathType: Prefix
          backend:
            service:
              name: phpmyadmin-k8s-t2-com
              port:
                number: 80
  ingressClassName: nginx

2.2.3 Access Effect

2.2 Multi-node single container mode B

2.2.1 Preparations

First prepare two t1 and t2 folders locally, and place an index.php in each

<?
echo "T1 Site is {$_SERVER['HTTP_HOST']}<br>";
phpinfo();
<?
echo "T2 Site is {$_SERVER['HTTP_HOST']}<br>";
phpinfo();

Upload to the corresponding path described in the configuration form

Screenshot of the current container group

2.2 Configure virtual host

In the KubeSphere background, go to Configuration – “Configuration Dictionary, in the nginx-conf configuration item, click Edit Settings

Add data items, t1.k8s-t1.com.conf & t2.k8s-t1.com.conf

server {
        listen 80;
        listen [::]:80;
        server_name t1.k8s-t1.com;
        
        index index.php index.html;
        error_log /var/log/nginx/t1.error.log;
        access_log /var/log/nginx/t1.access.log;
        root /var/www/html/t1;

        location ~ .*\.(gif|jpg|jpeg|png|bmp|swf|flv|mp4|ico)$ {
          expires 30d;
          access_log off;
        }

        location / {
            try_files $uri $uri/ /index.php?$query_string;
        }
        
        location ~ \.php$ {
            try_files $uri =404;
            fastcgi_split_path_info ^(. + \.php)(/. + )$;
            fastcgi_pass php:9000;
            fastcgi_index index.php;
            include fastcgi_params;
            fastcgi_param SCRIPT_FILENAME $document_root $fastcgi_script_name;
            fastcgi_param PATH_INFO $fastcgi_path_info;
        }

        error_page 500 502 503 504 /50x.html;
        location = /50x.html {
            root /usr/share/nginx/html;
        }
    }

After the completion, you need to restart the nginx pods, and you can access the verification results of these two domain names

3. Java Springboot App deployment

3.1 Create a springboot-hello project in VS Code

Pay attention to a few points:

  • Install docker desktop and use it with vscode development tools
  • Install the vscode plugin: Docker/Docker Exploer/Docker Extension Pack

3.2 Make App Mirror

Modify pom.xml and output App

<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.0.0</version>
</parent>

<modelVersion>4.0.0</modelVersion>
<groupId>com.itranswarp.learnjava</groupId>
<artifactId>springboot-hello</artifactId>
<version>1.0-SNAPSHOT</version>
<!-- <packaging>war</packaging> -->

<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<java.version>17</java.version>

<pebble.version>3.2.0</pebble.version>
</properties>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>provided</scope>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>

<!-- Integrate Pebble View -->
<dependency>
<groupId>io.pebbletemplates</groupId>
<artifactId>pebble-spring-boot-starter</artifactId>
<version>${pebble.version}</version>
</dependency>

<!-- JDBC driver -->
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
</dependency>
</dependencies>
<build>
<finalName>app</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<!-- Docker maven plugin -->
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<configuration>
<imageName>${project.artifactId}</imageName>
<imageTags>
<tag>1.0.0</tag>
</imageTags>
<dockerDirectory>src/main/docker</dockerDirectory>
<resources>
<resource>
<targetPath>/</targetPath>
<directory>${project.build.directory}</directory>
<include>${project.build.finalName}.jar</include>
</resource>
</resources>
</configuration>
</plugin>
<!-- Docker maven plugin -->
</plugins>
</build>
</project>

Write Dockerfile in the project root directory

FROM schnell18/zulu-java:alpine-jdk17-arm64-0.1.1
ADD ./target/app.jar /app.jar
ENTRYPOINT ["java","-jar","app.jar"]

Connect to your own registered warehouse and push hub.docker.com, as shown in the figure:

3.3 Deployment

springboothello.k8s-t2.com.yaml

# Service
apiVersion: v1
kind: Service
metadata:
  name: springboothello-k8s-t2-com
  namespace: iot-age
spec:
  type: ClusterIP
  #type: NodePort
  sessionAffinity: ClientIP
  sessionAffinityConfig:
    clientIP:
      timeoutSeconds: 10800
  ports:
  - port: 80
    #nodePort: 30301
    protocol: TCP
    targetPort: 8080
  selector:
    app: springboothello-k8s-t2-com

---
# deployment
apiVersion: apps/v1
kind: Deployment
metadata:
  name: springboothello-k8s-t2-com
  namespace: iot-age
spec:
  replicas: 2
  selector:
    matchLabels:
      app: springboothello-k8s-t2-com
  strategy:
    rollingUpdate:
      maxSurge: 25%
      maxUnavailable: 25%
    type: RollingUpdate
  template:
    metadata:
      labels:
        app: springboothello-k8s-t2-com
    spec:
      containers:
      - image: bennybi/springboothello:latest
        imagePullPolicy: Always
        name: springboothello-k8s-t2-com
        ports:
        - containerPort: 8080
          protocol: TCP
        resources:
          limits:
            memory: 512Mi
            cpu: "1"
          requests:
            memory: 512Mi
            cpu: "1"
      restartPolicy: Always
      terminationGracePeriodSeconds: 30
    
---
#Ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: springboothello-k8s-t2-com
  namespace: iot-age
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/affinity: cookie
    nginx.ingress.kubernetes.io/session-cookie-name: stickounet
    nginx.ingress.kubernetes.io/session-cookie-expires: "172800"
    nginx.ingress.kubernetes.io/session-cookie-max-age: "172800"
spec:
  rules:
    - host: springboothello.k8s-t2.com
      http:
        paths:
        - path: /
          pathType: Prefix
          backend:
            service:
              name: springboothello-k8s-t2-com
              port:
                number: 80
  ingressClassName: nginx

Access screenshot:

4. Session session persistence settings

This is the error encountered when using phpmyadmin:

Failed to set session cookie. Maybe you are using HTTP instead of HTTPS to access phpMyAdmin.

I quickly realized that this was caused by the out-of-sync sessions caused by access requests being assigned to different php pods for processing. Solution: set ingress, nginx service, and php service sessions to keep (that is, the same client ip access to the same pod, with an expiration time)

nginx.yaml

...
spec:
  type: ClusterIP
  sessionAffinity: ClientIP
  sessionAffinityConfig:
    clientIP:
      timeoutSeconds: 10800

php.yaml

...
spec:
  type: ClusterIP
  sessionAffinity: ClientIP
  sessionAffinityConfig:
    clientIP:
      timeoutSeconds: 10800

ingress-nginx.yaml

...
metadata:
  name: ia-web-service1
  namespace: iot-age
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/affinity: cookie
    nginx.ingress.kubernetes.io/session-cookie-name: stickounet
    nginx.ingress.kubernetes.io/session-cookie-expires: "172800"
    nginx.ingress.kubernetes.io/session-cookie-max-age: "172800"

5. Problems encountered

-Can’t use soft link to access the project directory, looking for a solution

6. Reference

– Pod research of Kubernetes (3)–Pod design pattern and life cycle_wx6325de70699f3’s technical blog_51CTO blog

– Talk about how to implement session persistence in K8S_k8s service session persistence_linyb Geek Road Blog-CSDN Blog

– Deployment of PHP projects on the Kubernetes platform using multiple Docker images

– https://medium.com/javarevisited/deploying-a-spring-boot-application-on-kubernetes-using-jenkins-672961425a42

The knowledge points of the article match the official knowledge files, and you can further learn relevant knowledge. Java skill treeHomepageOverview 118798 people are studying systematically

syntaxbug.com © 2021 All Rights Reserved.
pattern host domain name system point to hosts ip Project storage path
A phpmyadmin.k8s-t2 .com PHP 192.168.0.106 /var/ www/app
B t1.k8s-t1.com PHP 192.168.0.106 wwwroot/t1
B t2.k8s -t1.com PHP 192.168.0.106 wwwroot /t2
A springboothello.k8s-t2.com Java 192.168.0.106 /app.jar