K8S简化了应用的部署和维护工作,我以一个简单的应用为例子,试验如何在K8S来进行部署。

这个应用很简单,包括了一个Web的Rest接口以及一个PG的数据库。Rest接口返回数据库的查询结果。

PG数据库的搭建

数据库的搭建,选择Postgresql 11.15版本

下载镜像

docker pull postgres:11.15-alpine3.15

在主机上设置一个PG的数据目录

mkdir ~/pg_data

运行PG镜像测试

docker run --name my_postgres -v /home/roy/data/pg_volume:/var/lib/postgresql/data -e POSTGRES_PASSWORD=roy2000 -p 5555:5432 -d postgres:11.15-alpine3.15

之后连接本地的5555端口即可访问

psql -h 127.0.0.1 -p 5555 -U postgres

测试完成后,我们考虑如何在K8S上进行部署。数据库是一个有状态的应用,当数据库的Pod出现问题失败时,K8S会自动调度一个新的Pod,但是我们不能丢失原有的数据,因此需要把数据库的文件存储在PV上。我在本地搭建了一个NFS服务,把PV mount在NFS的文件路径上。

以下是创建PV的pv-volume.yaml文件,运行kubectl apply -f pv-volume.yaml来建立一个PV

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv01
  labels:
    type: local
spec:
  capacity:
    storage: 5Gi
  accessModes:
    - ReadWriteOnce
  nfs:
    path: /nfsroot/data
    server: 192.168.0.105

建立一个deployment的yaml文件,来进行PG的部署Deployment.yaml,在deployment里面,指定了数据库的名称,用户名,密码需要从configmap里面获取。

apiVersion: v1
kind: Service
metadata:
  name: myweb-pg
  labels:
    app: myweb
spec:
  ports:
    - port: 5555
      targetPort: pg
  selector:
    app: myweb
    tier: pg
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pg-pv-claim
  labels:
    app: myweb
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 3Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myweb-pg
  labels:
    app: myweb
spec:
  selector:
    matchLabels:
      app: myweb
      tier: pg
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: myweb
        tier: pg
    spec:
      containers:
      - image: postgres:11.15-alpine3.15
        name: pg11
        env:
        - name: POSTGRES_DB
          valueFrom:
            configMapKeyRef:
              name: postgres-config
              key: POSTGRES_DB
        - name: POSTGRES_USER
          valueFrom:
            configMapKeyRef:
              name: postgres-config
              key: POSTGRES_USER
        - name: POSTGRES_PASSWORD
          valueFrom:
            secretKeyRef:
              name: pg-pass
              key: password
        ports:
        - containerPort: 5432
          name: pg
        volumeMounts:
        - name: pg-persistent-storage
          mountPath: /var/lib/postgresql/data
      volumes:
      - name: pg-persistent-storage
        persistentVolumeClaim:
          claimName: pg-pv-claim

建立一个kustomization.yaml,里面定义了PG的配置信息,运行kubectl apply -k ./来创建

secretGenerator:
  - name: pg-pass
    literals:
    - password=YOUR_PASSWORD
resources:
  - pg_deployment.yaml

Deployment创建了之后,运行kubectl get svc来查看创建的service, 然后连接这个service的IP:5555端口测试,例如运行指令psql -h serviceIP -p 5555 -U username -d databasename

Web应用的搭建

搭建一个web应用,提供一个REST接口,查询数据库的内容。

这里我选择了Quarkus这个微服务,可以参考quarkus.io官网,里面有很详细的教程。我的代码可见仓库gzroy/products

这里有一点需要提到的,在这个代码中,我是选择了Quarkus reactive的方式来构建一个异步的接口,然后用flyway来进行数据库的初始化。因为reactive方式和flyway方式指定的数据库连接方式不同,不能并存,因此需要做一些改动。以下是application.properties的设定,这里只能设定quarkus.datasource.reactive.url,不能同时设定datasource.jdbc.url。并且datasource.jdbc需要设置为false。在reactive.url里面设定的是我们刚才K8S里面建立的PG数据库的service的名称

quarkus.datasource.db-kind=postgresql
quarkus.hibernate-orm.database.generation=drop-and-create
quarkus.http.port=9090
quarkus.datasource.reactive.url=postgresql://myweb-pg.default.svc.cluster.local:5555/products
quarkus.datasource.username=abc
quarkus.datasource.password=12345
quarkus.flyway.migrate-at-start=false
quarkus.datasource.jdbc=false
quarkus.flyway.baseline-on-migrate=true

另外需要新建一个service来在应用开始出发flyway的migrate,如以下代码:

@ApplicationScoped
public class FlywayMigrationService {
    
    @ConfigProperty(name = "quarkus.datasource.reactive.url")
    String datasourceUrl;
    @ConfigProperty(name = "quarkus.datasource.username")
    String datasourceUsername;
    @ConfigProperty(name = "quarkus.datasource.password")
    String datasourcePassword;

    public void runFlywayMigration(@Observes StartupEvent event) {
        Flyway flyway = Flyway.configure().dataSource("jdbc:" + datasourceUrl, datasourceUsername, datasourcePassword).load();
        flyway.clean();
        flyway.migrate();
    }
}

编译代码并打包为docker镜像。然后建立一个web_deploymen.yaml:

apiVersion: v1
kind: Service
metadata:
  name: myweb-backend
  labels:
    app: myweb
spec:
  ports:
    - port: 9090
      targetPort: product
  selector:
    app: myweb
    tier: backend
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myweb-backend
  labels:
    app: myweb-backend
spec:
  selector:
    matchLabels:
      app: myweb
      tier: backend
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: myweb
        tier: backend
    spec:
      containers:
      - image: quarkus/products-jvm:latest
        name: product
        imagePullPolicy: Never
        ports:
        - containerPort: 9090
          name: product

修改一下kustomization.yaml,把这个新的deployment加进去:

secretGenerator:
  - name: pg-pass
    literals:
    - password=XXXXXX
configMapGenerator:
  - name: postgres-config
    literals:
      - POSTGRES_DB=products
      - POSTGRES_USER=roy
resources:
  - pg_deployment.yaml
  - web_deployment.yaml

最后运行kubectl apply -k ./,用kubectl get svc查看新建的web service,然后curl http://serviceIP:9090/products,即可看到返回结果。

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐