docker&k8s deployment tomcat record

Description of parameters

The replacement parameters used in the following are described:

${env}: environment variables, which describe the development environment, test environment, and use namespaces to distinguish environments on k8s, so first you need to create a namespace: kubectl create namespace ${env}, namespace names can only be alphabetical data connectors (-);

${group}: project group name, or product line name;

${appName}: application name;

${version}: application version;

${repository}: docker repository

Deployment process description

Step 1: Generate a specific Docker file

The Dockerfile template is as follows:

FROM ${repository}/xxxx/base:v4.0
MAINTAINER xxxx@xxxx.cn
COPY ./ROOT.war  /root/tomcat/webapps
CMD ["/root/init.sh"]

Explain:

  1. The application Dockerfile inherits the basic image, copies the war package to tomcat's webapps directory, and sets the startup command to be init.sh script.
  2. Basic Mirror: Use Minimum linux Version: Alpine, JRE Dependent on glibc: bash, glibc, jre, tomcat need to be added on the basis of from alpine. The working directory of Tomcat is / root/tomcat. See the annex section for details.
  3. Applications can also mount ROOT onto the basic image container using shared read-write volumes instead of creating mirrors. This practice is not recommended.

Step 2: Create a mirror

docker rmi -f ${repository}/${group}/${appName}:${version}
docker build -t ${repository}/${group}/${appName}:${version}  --no-cache   -f Dockerfile-${appName}-${env} .

Delete existing mirrors and create new ones.
The name of the image created: ${repository}/${group}/${appName}:${version}

Step 3: Submit the mirror

docker login ${repository} -u admin -p password
docker push ${repository}/${group}/${appName}:${version}

Login to the warehouse and submit the image.

Step 4: Allocate application ports

The ports of applications are managed by configMap. When ports are needed, configMap is exported to get the application ports. The configMap file template is as follows:

apiVersion: v1
kind: ConfigMap
metadata:
  name: ${env}-env
  namespace: ${env}
data:
  ${appName1}.applicationName: xxxxxx
  ${appName1}.port: "30001"
  ${appName2}.applicationName: yyyyyy
  ${appName2}.port: "30101"

Explain:
Environment Name: corresponds to the environment Name in the original setenv.sh;
ZookeeperUrl: corresponding to the original setenv.zookeeperUrl; ${appName1}: Apply identifier, cannot use underscore;
ApplicationName: ${appName1} setenv.applicationName: corresponding to the original application ${appName1} setenv.applicationName;
${appName1}.port: The tomcat port assigned to the application ${appName1} where the port must be double quoted;

Create configMap: kubectl create -- save-config-f configMap - ${env}. yaml

If configMap already exists: there are two ways to upgrade 1) recreate: delete configMap and create it again;
2) rolling upgrade: kubectl apply-f configMap - ${env}.yaml

Step 5: Define deployment,service

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: ${appName}
  namespace: ${env}
  labels:    
    app: ${appName}
spec:
  replicas: 1
  selector:
    matchLabels:
      app: ${appName}
  template:
    metadata:
      labels:
        app: ${appName}
    spec:
      containers:
      - name: ${appName}
        imagePullPolicy: Always 
        image: ${repository}/${group}/${appName}:${version}
        env:        
        - name: port
          valueFrom:
            configMapKeyRef:
              name: ${env}-env
              key: ${appName}.port
        ports:
        - containerPort: %port%
        volumeMounts:
        - mountPath: "/pv"
          name: hp-${appName}-${env}
      volumes:
      - name: hp-${appName}-${env}
        hostPath:
          path: /data/k8s_volume/${appName}-${env}
      tolerations:
      - key: "CriticalAddonsOnly"
        operator: "Exists"

Explain:

  • The ports of tomcat, pod, service and node need to be consistent before they can be accessed. Why is it not clear? Service port limit is 30000-80000, node port limit is 0-32767, so configurable port range is 30000-32767.
  • spec.selector is used to specify label selector and delineate the pod range managed by Deployment. If specified, the. spec.selector must match. spec.template.metadata.labels, otherwise it will be rejected by the API.
  • namespace: Use ${env} to partition
  • The environment variables that set up the pod container are: port. They are all obtained from the configMap of ${env}-env
  • Image Pull Policy is set to Always, always pulling mirrors from the warehouse
  • Persistent volume: The data volume used by pod is set to read and write shared nfs persistent volume. Detailed definitions can be found in the annex section.
apiVersion: v1
kind: Service
metadata:
  name: ${appName}
  namespace: ${env}
  labels:
    app: ${appName}
spec:
  type: NodePort 
  selector:
    app: ${appName}
  ports:
  - port: %port%
    targetPort: %port%
    nodePort: %port%

Explain:

  • type: Use NodePort: Assign a virtual IP accessible within the cluster to the service and bind a port on the node so that the service can be accessed through <NodeIP>: NodePort.
  • Selector: Use selector to select pod to generate endpoint.
  • port: port for service monitoring
  • targetPort: Port that needs to be forwarded to the back-end pod
  • nodePort: Port number of physical machine node

Step 6: Create deployment,service

port=`kubectl get configmap ${env}-env -n ${env} -o yaml|grep ${appName}.port|awk -F '"' '{print $2}'`
sed -i "s/%port%/$port/g" ${appName}-${env}.yaml
kubectl create --save-config -f ${appName}-${env}.yaml

Get the port from configmap, replace the placeholder in the yaml file, and create the resources defined in the yaml file.

Upgrade process description

Two ways: 1) recreate: delete the application pod, deployment automatically retrieves the mirror to create a new podkubectl delete pod name - n ${env};
2) rolling upgrade: kubectl apply-f ${appName} - ${env}. yaml

Basic Mirror Dockerfile

FROM alpine:latest
MAINTAINER xxx@xx.cn

ENV tomcat_home=/root/tomcat \
    JAVA_HOME=/root/jre1.7.0_80 \
    PATH=$JAVA_HOME/bin:$PATH \
    LANG=zh_CN.UTF-8 \
    TZ="Asia/Shanghai"  \
    GLIBC_PKG_VERSION=2.23-r1

ADD ./jre-7u80-linux-x64.gz /root
COPY ./tomcat $tomcat_home
COPY ./init.sh /root

WORKDIR /tmp

RUN chmod  775 /root/init.sh && \
  echo "https://mirrors.aliyun.com/alpine/v3.6/main">/etc/apk/repositories && \
  apk add --no-cache --update-cache wget ca-certificates bash bash-doc bash-completion && \
  wget -q -O /etc/apk/keys/sgerrand.rsa.pub https://raw.githubusercontent.com/sgerrand/alpine-pkg-glibc/master/sgerrand.rsa.pub && \
  wget https://github.com/sgerrand/alpine-pkg-glibc/releases/download/${GLIBC_PKG_VERSION}/glibc-${GLIBC_PKG_VERSION}.apk && \
  wget https://github.com/sgerrand/alpine-pkg-glibc/releases/download/${GLIBC_PKG_VERSION}/glibc-bin-${GLIBC_PKG_VERSION}.apk && \
  wget https://github.com/sgerrand/alpine-pkg-glibc/releases/download/${GLIBC_PKG_VERSION}/glibc-i18n-${GLIBC_PKG_VERSION}.apk && \
  apk add glibc-${GLIBC_PKG_VERSION}.apk glibc-bin-${GLIBC_PKG_VERSION}.apk glibc-i18n-${GLIBC_PKG_VERSION}.apk && \  
  apk del curl ca-certificates && \
  rm -rf /tmp/* /var/cache/apk/* 

init.sh startup script

#!/bin/bash
#sed -i 's/autoDeploy="true">/autoDeploy="true"><Context path="" docBase="\/pv\/war\/ROOT.war"\/>/' $tomcat_home/conf/server.xml 
sed -i "s/8080/$port/" $tomcat_home/conf/server.xml
sh  $tomcat_home/bin/startup.sh
tail -F $tomcat_home/logs/catalina.out

Persistent Volume Definition

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-nfs
  namespace: ${env}
spec:
  capacity:
    storage: 50Gi
  accessModes:
    - ReadWriteMany
  persistentVolumeReclaimPolicy: Retain
  nfs:
    path: /data/k8s_volume
    server: 192.168.0.1

---

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: pv-nfs
  namespace: ${env}
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 50Gi

Best Practices

1) ENV RUN Writes in a New Line
2) CMD is recommended, followed by ENTRYPOINT
3) Export compression layer:

docker run --name demo base:v3.0 echo ForExport  
docker export --output base4.0.tar demo  
docker rm demo  
docker import base4.0.tar base:v4.0

4)ONBUILD
5) docker history view mirror layer
6). dockerignore ignores files
7) Using chmod-R 775 directory without compression, the final image will be very large

Pit

  • The parameters in the parameterized construction of jenkins are similar to the naming specifications of the general parameters. You can't use the ${} reference to replace the $in the shell script, and you can create another parameter with the same name.
  • Container created by docker default user root
  • Create mirror ADD command error reporting: Forbidden path outside the build context:..
  • docker restart, kubelet also needs to restart
  • COPY. / Tomcat / root / Tomcat Dockerfile COPY,
  • data source rejected establishment of connection message from server too manay connections
  • executable file not found"and"no such file: shell return problem written under windows" http://www.linuxidc.com/Linux/2011-09/42618.htm

Relevant orders

1) Building image from Dockerfile:
docker build -t xxxxxl:v1.0.002 -f Dockerfile-xxxxx .

2) Run image to generate container:
docker run -d -p 30101:30101 --name xxxxx xxxx:v1.0.002

3) Interacting with container:
docker exec -it xxxxx /bin/bash

Keywords: Docker glibc Tomcat Linux

Added by Ristiisa on Fri, 07 Jun 2019 01:25:42 +0300