在K8S里面容器化 php 项目

简介

本章内容将把传统 php 项目转移到 k8s 集群中运行,将开发环境从 docker-compose 迁移到 k8s 。

Docker Compose 下的 php

一个 docker-compose.yaml 文件搞定,主要是拆分为 nginx 和 fpm 容器,如果还用到其它服务,就需要额外引入,如 mysql ,redis,kafka,es 等。

docker-composer.yaml:

version: '3'

networks:
  web-network:
    driver: bridge

services:
  fpm:
    build:
      context: ./fpm
    volumes:
      - "./nginx/apps:/var/www/html:cached"
      - "./fpm/php-fpm.d:/usr/local/etc/php-fpm.d:cached"
      - "./fpm/php.ini:/usr/local/etc/php/php.ini"
    networks:
      - web-network

  nginx:
    build:
      context: ./nginx
    ports:
      - '80:80'
    volumes:
      - ./nginx/apps:/var/www/html:cached
      - ./nginx/conf:/etc/nginx/conf.d:cached
      - ./nginx/log:/var/log/nginx
    networks:
      - web-network

就这样,一个最简单的 php 环境就搭好了,至于 Dockerfile ,直接根据官方镜像做自定义调整就好了,nginx 的话基本不需要调整,简单做下配置和代码的映射就好了;fpm 的话除了做配置和代码映射,还需要安装扩展和 composer 等基本工具。

fpm Dockerfile:

FROM php:7.2-fpm

ADD install-php-extensions /usr/local/bin/

RUN apt-get update && apt-get install -y wget git vim ruby zlib1g-dev nodejs npm

RUN docker-php-ext-install pdo_mysql
RUN docker-php-ext-install bcmath
RUN docker-php-ext-install mysqli
RUN docker-php-ext-install sockets

RUN chmod uga+x /usr/local/bin/install-php-extensions && sync
RUN install-php-extensions redis
RUN install-php-extensions zip
RUN install-php-extensions pcov
RUN install-php-extensions pcntl
RUN install-php-extensions gd exif
RUN install-php-extensions xlswriter
RUN install-php-extensions swoole

COPY --from=composer:2.0.12 /usr/bin/composer /usr/local/bin/composer

fpm 官方镜像提供了 docker-php-ext-install 命令快速安装扩展,但是安装的扩展数量有限,推荐使用 install-php-extensions 脚本安装,几乎任何项目中用到的扩展都可以找得到。

nginx 怎样访问到 fpm 容器?因为使用的是同一个网络,所以直接使用服务名,nginx.conf:

upstream fpm {
    server fpm:9000;
}

server {
    listen       80;
    server_name  purelight.me;

    access_log  /var/log/nginx/purelight.me.access.log  main;
    error_log /var/log/nginx/purelight.me.error.log;
    root   /var/www/html/purelight/public;

    location / {
        index  index.html index.php;
        try_files $uri $uri/ /index.php$is_args$args;
    }

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

    location ~ \.php$ {
        fastcgi_pass   fpm;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include        fastcgi_params;
    }
}

同样,对于 fpm 容器,就可以直接通过 mysql 服务名作为 host 去连接。

docker-compose up -d 就可以让 compose 完成镜像构建,容器启动,使用的 volume ,所以代码更改也可以实时看到效果,非常适合本地开发。

线上基本无法直接使用 docker compose ,因为它功能太少了,负载均衡,自动故障恢复,存活检测等都不太好完成,基本都是用 k8s ,所以考虑将本地环境升级到 k8s 。

K8S 下的 php

K8S 里面是以 Pod 为最小单位,所以将 nginx 和 fpm 放进一个 pod ,做个简单的 k8s-demo 。

创建命名空间
kubectl create namespace k8s-demo
创建 Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
  namespace: k8s-demo
  name: k8s-com-deployment
  labels:
    app: k8s-com
    version: v1
spec:
  replicas: 2
  selector:
    matchLabels:
      app: k8s-com
      version: v1
  template:
    metadata:
      labels:
        app: k8s-com
        version: v1
    spec:
      containers:
        - name: nginx
          image: nginx:1.20.0
          ports:
            - containerPort: 80
          volumeMounts:
            - name: confd
              mountPath: /etc/nginx/conf.d
            - name: www
              mountPath: /var/www
            - name: logs
              mountPath: /var/log/nginx
        - name: fpm
          image: php:7.2-fpm
          ports:
            - containerPort: 9000
          volumeMounts:
            - name: www2
              mountPath: /var/www
      volumes:
        - name: confd
          hostPath:
            path: /Users/purelightme/Desktop/purelight-k8s/images/nginx/conf.d
        - name: www
          hostPath:
            path: /Users/purelightme/Desktop/purelight-k8s/images/nginx/www
        - name: www2
          hostPath:
            path: /Users/purelightme/Desktop/purelight-k8s/images/nginx/www
        - name: logs
          hostPath:
            path: /Users/purelightme/Desktop/purelight-k8s/images/nginx/logs
        - name: ini
          hostPath:
            path: /Users/purelightme/Desktop/purelight-k8s/images/fpm/php.ini
        - name: fpmd
          hostPath:
            path: /Users/purelightme/Desktop/purelight-k8s/images/fpm/php-fpm.d

因为是本地环境,所以选择 hostPath 挂载到 pod ,生产环境应该直接把配置和代码打包到镜像里面去。

创建 Service
apiVersion: v1
kind: Service
metadata:
  namespace: k8s-demo
  name: k8s-com-service
  labels:
    app: k8s-com
    version: v1
spec:
  type: NodePort
  selector:
    app: k8s-com
    version: v1
  ports:
   - port: 80
     targetPort: 80

这里 type 应该选择 ClusterIP (后面通过 ingress 暴露出去),这里用 NodePort 的话就可以直接在本机访问了。

这里 selector 选择的是 pod 的标签,而不是 deployment 的。

启动 nginx ingress controller
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v0.45.0/deploy/static/provider/cloud/deploy.yaml
创建 Ingress
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: k8s-ing
  namespace: k8s-demo
spec:
  rules:
  - host: k8s.com
    http:
      paths:
      - path: /
        backend:
          serviceName: k8s-com-service
          servicePort: 80

本机配置 host 之后,就可以直接访问 http://k8s.com 了,ingress 捕捉到请求后将请求转发到 k8s-com-service service。同时也可以通过 kubectl get svc -n k8s-demo 找到 NodePort 的端口,访问 http://k8s.com:32457 也可以访问到服务,但是这种方式不会经过 ingress ,而是直接又 service 完成。

效果图:

33-01.png

总结

不同的站点,我们应该用多个 pod 去实现,而不是把所有 site 都放进一个 pod ,站点间可以通过 service 名称直接通信 。Ingress 有很多配置项,支持7层代理,这样的话就可以实现动态负载均衡,其作为流量入口,可以提供前置和后置的功能,如认证授权,速率控制,日志搜集,统计等。

在传统的 web 开发里面,我们最后是要把代码上传到生产服务器上,在容器环境里面,我们就需要关注镜像了,可以说我们最后的产物就是打造一个又一个镜像,发布的过程就是更新 pod 镜像版本的过程。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342

推荐阅读更多精彩内容