前言
? ? ? ? 前端時(shí)間PHP項(xiàng)目部署升級(jí)需要 ,需要把Laravel開(kāi)發(fā)的項(xiàng)目部署K8s上,下面以laravel項(xiàng)目為例,講解采用yaml文件方式部署項(xiàng)目。
一、部署步驟
1.創(chuàng)建Dockerfile文件
Dockerfile是一個(gè)用來(lái)構(gòu)建鏡像的文本文件,在容器運(yùn)行時(shí),需要把項(xiàng)目文件和項(xiàng)目運(yùn)行所必須的組件安裝其中。
# 基礎(chǔ)鏡像
FROM php:7.4-fpm
# 時(shí)區(qū)
ARG TZ=Asia/Shanghai
# 更換容器時(shí)區(qū)
RUN cp "/usr/share/zoneinfo/$TZ" /etc/localtime && echo "$TZ" > /etc/timezone
# 替換成阿里apt-get源
RUN sed -i "s@http://deb.debian.org@http://mirrors.aliyun.com@g" /etc/apt/sources.list && rm -rf /var/lib/apt/lists/* && cat /etc/apt/sources.list
# 調(diào)試擴(kuò)展
# vim net-tools rsyslog procps
# 安裝擴(kuò)展
RUN apt-get update \
&& apt-get install -y libzip-dev zip libfreetype6-dev libjpeg62-turbo-dev libmcrypt-dev librdkafka-dev libpng-dev cron supervisor \
&& rm -rf /var/lib/apt/lists/* \
&& docker-php-ext-configure gd \
&& docker-php-ext-install -j$(nproc) gd mysqli pdo_mysql zip opcache bcmath iconv
# 安裝kafka擴(kuò)展
COPY deploy/docker/php/ext/rdkafka-5.0.0.tgz /tmp/
RUN pecl install /tmp/rdkafka-5.0.0.tgz && docker-php-ext-enable rdkafka
# 安裝redis擴(kuò)展
COPY deploy/docker/php/ext/redis-5.3.4.tgz /tmp/
RUN pecl install /tmp/redis-5.3.4.tgz && docker-php-ext-enable redis
# 創(chuàng)建supervisor日志目錄、項(xiàng)目目錄
RUN mkdir -p /var/log/supervisor && mkdir -p /www
# supervisor配置文件
COPY deploy/docker/supervisor/conf.d /etc/supervisor/conf.d
# 替換php配置文件
COPY ./deploy/docker/php/conf.d/opcache.ini /usr/local/etc/php/
COPY ./deploy/docker/php/conf.d/phpcustom.ini /usr/local/etc/php/
# CPOY定時(shí)任務(wù)
COPY deploy/docker/cron/root /var/spool/cron/crontabs
RUN chmod 600 /var/spool/cron/crontabs/root
# 安裝composer
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer \
&& ln -s $(composer config --global home) /root/composer \
&& composer config -g repo.packagist composer https://packagist.phpcomposer.com
# COPY項(xiàng)目到/www目錄
COPY . /www
# 進(jìn)入/www目錄
WORKDIR /www
# 刪除多余文件
RUN rm -rf $(find /www/backend/ -maxdepth 1 ! -name "backend" ! -name "dist") && rm -rf /tmp/*
# /www下文件授權(quán)用戶組和用戶權(quán)限;composer安裝需要包(如果項(xiàng)目composer存在,可不執(zhí)行)
RUN chown -R www-data:www-data /www/storage \
&& composer install \
--optimize-autoloader \
--ignore-platform-reqs \
--prefer-dist \
--no-interaction \
--no-dev
# 執(zhí)行entrypoint
COPY deploy/docker/entrypoint.sh /usr/local/bin/entrypoint
RUN chmod +x /usr/local/bin/entrypoint
ENTRYPOINT ["/usr/local/bin/entrypoint"]
2. 創(chuàng)建命名空間【namespace.yaml】
Kubernetes使用命名空間的概念幫助解決集群中在管理對(duì)象時(shí)的復(fù)雜性問(wèn)題。命名空間允許將對(duì)象分組到一起,便于將它們作為一個(gè)單元進(jìn)行篩選和控制;簡(jiǎn)單理解可以實(shí)現(xiàn)項(xiàng)目彼此隔離。
- 創(chuàng)建Namespace
????????kubectl create -f namespace.yaml
- 查看所有Namespace
? ? ? ? ?kubectl get namespaces
apiVersion: v1 #版本號(hào)
kind: Namespace #配置類型
metadata: #元數(shù)據(jù)
name: php-service #該 Namespace 的名稱
3. 創(chuàng)建App Env Config【app-env-config.yaml】(laravel .env 配置)
- 創(chuàng)建App Env Config
? ? ? ? ??kubectl create -f app-env-config.yaml
- 查看該命名空間所有Config
? ? ? ? ??kubectl get --namespace=php-service configmaps
- 查看該Config
? ? ? ? ? kubectl get --namespace=php-service configmaps app-env-config
- 查看該Conifg Yaml
? ? ? ? ??kubectl get --namespace=php-service configmaps app-env-config -o yaml
apiVersion: v1 #版本號(hào)
kind: ConfigMap #配置類型
metadata: #元數(shù)據(jù)
name: app-env-config #該 ConfigMap 的名稱
namespace: php-service #該 ConfigMap 所在命名空間
data: #該 ConfigMap 數(shù)據(jù)
# App Config
APP_DEBUG: 'true'
APP_ENV: test
APP_KEY: xxx
# DB Config
DB_DATABASE: xxx
DB_HOST: xx.xx.xx.xx
DB_PASSWORD: xxx
DB_USERNAME: xxx
# JWT Config
JWT_KEY: XXX
JWT_SECRET: XXX
JWT_TOKEN_EXPIRE_TIME: '86400'
# Redis Config
REDIS_DATABASE: '0'
REDIS_HOST: xx.xx.xx.xx
REDIS_PASSWORD: xxx
REDIS_PORT: '6380'
REDIS_PREFIX: xxx
4. 創(chuàng)建Nginx Config【nginx-config.yaml】
- 創(chuàng)建Nginx Config
? ? ? ? ? ?kubectl create -f nginx-config.yaml
- 查看該創(chuàng)建Config
? ? ? ? ? kubectl get --namespace=php-service configmaps
- 查看該Conifg Yaml
? ? ? ? ??kubectl get --namespace=php-service configmaps nginx-config -o yaml
apiVersion: v1 #版本號(hào)
kind: ConfigMap #配置類型
metadata: #元數(shù)據(jù)
name: nginx-config #該 ConfigMap 的名稱
namespace: php-service #該 ConfigMap 所在命名空間
data: #數(shù)據(jù)
nginx_conf: |-
user www-data;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
server {
listen 80;
server_name _;
root /var/www/html/public;
index index.php;
#charset koi8-r;
#access_log /var/log/nginx/log/host.access.log main;
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
location / {
try_files $uri $uri/ /index.php?$query_string;
}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
location ~ \.php$ {
include fastcgi_params;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass 127.0.0.1:9000;
}
location /backend/ {
index index.html;
alias /var/www/html/backend/dist/;
}
location /statics/{
alias /var/www/html/backend/dist/statics/;
}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}
}
5. 創(chuàng)建Nginx Service【nginx-service.yaml】
- 創(chuàng)建Nginx Service
? ? ? ? ? ?kubectl create -f nginx-service.yaml
- 查看該Service
? ? ? ? ? ?kubectl get --namespace=php-service service -o wide
- 查看該Service Yaml
? ? ? ? ? ?kubectl get --namespace=php-service service nginx-service -o yaml
apiVersion: v1 #版本號(hào)
kind: Service #配置類型
metadata: #元數(shù)據(jù)
name: nginx-service #該Service 的名稱
namespace: php-service #該 Service 所在命名空間
labels: #標(biāo)簽
app: nginx #為該 Service 設(shè)置 key 為 app,value 為 nginx 的標(biāo)簽
spec: #關(guān)于該 Service 的定義,描述了 Service 如何選擇 Pod,如何被訪問(wèn)
selector: #標(biāo)簽選擇器
app: kayaka #選擇包含標(biāo)簽 app:kayaka 的Pod
type: NodePort #Serive的類型,ClusterIP/NodePort/LoaderBalancer
ports:
- name: http #端口的名字
protocol: TCP #協(xié)議類型 TCP/UDP
port: 80 #集群內(nèi)的其他容器組可通過(guò) 80 端口訪問(wèn) Service
#port: 30080 #通過(guò)任意節(jié)點(diǎn)的 32600 端口訪問(wèn) Service,不固定自動(dòng)設(shè)置
targetPort: 80 #將請(qǐng)求轉(zhuǎn)發(fā)到匹配 Pod 的 80 端口
6. 創(chuàng)建App?Deployment【app-deployment.yaml】(主要采用 POD-容器組(php-fpm和nginx)的方式)
- 創(chuàng)建App Deployment
? ? ? ? ? kubectl apply -f app-deployment.yaml
- 查看該命名空間所有Deployment
? ? ? ? ? kubectl get --namespace=php-service deployments -o wide
- 查看該Deployment
? ? ? ? ? kubectl get --namespace=php-service deployments kayaka -o wide
- 查看該Deployment Yaml
? ? ? ? ? kubectl get --namespace=php-service deployments kayaka -o yaml? ?
apiVersion: apps/v1 #與k8s集群版本有關(guān),使用 kubectl api-versions 即可查看當(dāng)前集群支持的版本
kind: Deployment #配置類型,這里使用的是 Deployment
metadata: #元數(shù)據(jù),即 Deployment 的一些基本屬性和信息
name: kayaka #該Deployment 的名稱
namespace: php-service #Pod所屬的命名空間
labels: #標(biāo)簽,可以靈活定位一個(gè)或多個(gè)資源,其中key和value均可自定義,可以定義多組
app: kayaka #為該Deployment設(shè)置key為app,value為nginx的標(biāo)簽
spec: #該Deployment的描述,可以理解為你期待該Deployment在k8s中如何使用
selector: #標(biāo)簽選擇器,與上面的標(biāo)簽共同作用,目前不需要理解
matchLabels: #選擇包含標(biāo)簽app:kayaka的資源
app: kayaka
replicas: 2 #使用該Deployment創(chuàng)建幾個(gè)應(yīng)用程序?qū)嵗? strategy: #更新策略
type: RollingUpdate #Recreate 重新創(chuàng)建 RollingUpdate 滾動(dòng)升級(jí)
template: #選擇或創(chuàng)建的Pod的模板
metadata: #Pod的元數(shù)據(jù)
labels: #Pod的標(biāo)簽,上面的selector即選擇包含標(biāo)簽app:kayaka的Pod
app: kayaka
spec: #期望Pod實(shí)現(xiàn)的功能(即在pod中部署)
containers: #生成container,與docker中的container是同一種
- name: kayaka #container的名稱
image: harbor.dobest.com/tfctest/kayaka:1.0.0 #鏡像地址
imagePullPolicy: Always #鏡像拉取策略 Always 總是拉去、IfNotPresent 優(yōu)先使用本地、Never 僅使用本地
ports: #容器端口
- containerPort: 9000
#env:
#- name: REDIS_HOST
#value: redis-service
envFrom: #ENV 配置來(lái)源(無(wú)法熱更新)
- configMapRef:
name: app-env-config
volumeMounts: #掛載到容器內(nèi)部的存儲(chǔ)卷配置
- name: nginx-www #引用pod定義的共享存儲(chǔ)卷的名稱,需用volumes[]部分定義的的卷名
mountPath: /var/www/html #存儲(chǔ)卷在容器內(nèi)mount的絕對(duì)路徑
readOnly: false #是否為只讀模式
lifecycle: #container 的生命周期
postStart: #容器開(kāi)始啟動(dòng)執(zhí)行事件
exec:
command: [ "/bin/sh","-c","cp -r /www/* /var/www/html && chown -R www-data:www-data /var/www/html/storage" ]
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
volumeMounts:
- mountPath: /var/www/html
name: nginx-www
- mountPath: /etc/nginx/nginx.conf
subPath: nginx.conf
name: nginx-config
volumes: #該pod上定義共享存儲(chǔ)卷列表
- name: nginx-www #共享存儲(chǔ)卷名稱 (volumes類型有很多種)
emptyDir: { } #類型為emtyDir的存儲(chǔ)卷,與Pod同生命周期的一個(gè)臨時(shí)目錄。為空值
- name: nginx-config #共享存儲(chǔ)卷名稱(volumes類型有很多種)
configMap: #類型為configMap的存儲(chǔ)卷,掛載預(yù)定義的configMap對(duì)象到容器內(nèi)部
name: nginx-config
items:
- key: nginx_conf
path: nginx.conf
7. 創(chuàng)建Ingress【ingress.yaml】路由
- 創(chuàng)建Ingress
? ? ? ? ??kubectl apply -f ingress.yaml
- 查看該命名空間所有Ingress
? ? ? ? ? kubectl get --namespace=php-service ingress -o wide
- 查看該Ingress
? ? ? ? ? kubectl get --namespace=php-service ingress ingress文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-445663.html
- 查看該Ingress Yaml
? ? ? ? ? kubectl get --namespace=php-service ingress ingress -o yaml? ?文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-445663.html
apiVersion: extensions/v1beta1 #版本號(hào)
kind: Ingress #配置類型
metadata: #元數(shù)據(jù)
name: ingress #該 Ingress 的名稱
namespace: php-service #該 Ingress 所在命名空間
labels: #標(biāo)簽
app: ingress
spec: #該 Ingress 的描述
rules: # 規(guī)則
- host: test-kyk.sanguosha.com # 域名
http:
paths: # 路徑
- backend:
serviceName: nginx-service #服務(wù)名稱
servicePort: 80 #服務(wù)端口
path: /
注意事項(xiàng)
-
更新 ConfigMap?
- 使用該 ConfigMap 掛載的 Env 不會(huì)同步更新
- 使用該 ConfigMap 掛載的 Volume 中的數(shù)據(jù)需要一段時(shí)間(實(shí)測(cè)大概10秒)才能同步更新
- ENV 是在容器啟動(dòng)的時(shí)候注入的,啟動(dòng)之后 kubernetes 就不會(huì)再改變環(huán)境變量的值,且同一個(gè) namespace 中的 pod 的環(huán)境變量是不斷累加的,為了更新容器中使用 ConfigMap 掛載的配置,可以通過(guò)滾動(dòng)更新 pod 的方式來(lái)強(qiáng)制重新掛載 ConfigMap
-
定時(shí)任務(wù)問(wèn)題
- 當(dāng)Pod個(gè)數(shù)大于1時(shí),每個(gè)Pod中容器都存在定時(shí)任務(wù),為了避免定時(shí)任務(wù)沖突,可以使用Redis分布式鎖,使定時(shí)任務(wù)在其中一個(gè)Pod中執(zhí)行。
-
項(xiàng)目日志問(wèn)題
- laravel日志默認(rèn)寫入文件,日志寫入pod中,我們也可創(chuàng)建存儲(chǔ)類,但查看日志又存在問(wèn)題,所以建議寫入kafka中,再去消費(fèi)處理日志。
到了這里,關(guān)于K8s部署PHP項(xiàng)目的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!