
Esta é uma breve observação sobre como empacotar o aplicativo vue.js no Dockerfile e, em seguida, executá-lo em um contêiner no kubernetes'e.
O que faz
Eu escrevi um pequeno programa que gera um número NodePort gratuito. Na verdade, ela não faz nada particularmente útil, mas você não precisa se preocupar com a busca de um porto e, por diversão, veja como isso pode ser feito.
Iniciado
Todo o projeto consiste em duas partes - frontend e servidor. O front-end pede ao nodePort do servidor e o lado do servidor encontra alguns de graça através da API do kubernetes.
Na verdade, para que isso funcione na janela de encaixe, é necessário extrair algumas variáveis do aplicativo, como o endereço kubernetes api, porta, token, etc.
É assim:
k8s-nodeport-gen/server/index.js: var k8sInfo = { url: process.env.K8SURL, port: process.env.K8SPORT, timeout: process.env.K8STIMEOUT || '30', respath: process.env.RESSPATH || '/api/v1/services', token: process.env.K8STOKEN, nodePortStart: process.env.K8SPORTSTART || '30000', nodePortEnd: process.env.K8SPORTEND || '32000' } app.listen(process.env.PORT || 8081)
Digamos que tudo foi testado e nosso aplicativo funciona.
Criar uma imagem de janela de encaixe
Quem trabalhou com o vue.js sabe que existem muitos tipos de arquivos, dos quais todos são necessários, eu não sei, mas eles precisam ser vistos. Mas, graças ao fato de existir o vue-cli, tudo pode ser simplesmente empacotado. Agora nós embalamos tudo:
npm run build
Depois disso, teremos a pasta "dist" e o arquivo "index.html" em "k8s-nodeport-gen / client". E para o trabalho, precisamos apenas deles. Isto é, em teoria, para o frontend funcionar, você precisa de algum tipo de servidor http. Mas, neste caso, também há um back-end, que também deve funcionar. Portanto, no meu caso, como um servidor http, o node.js express funcionará.
Os arquivos estarão mais tarde na pasta k8s-nodeport-gen / public. Para fazer isso, adicione a opção ao server / index.js
app.use(express.static(__dirname + '/public'))
Agora que você analisou os arquivos, pode criar um Dockerfile. Nós, do front-end, precisamos apenas criar arquivos para a pasta "dist". Para fazer isso, usaremos algo tão novo como a compilação de vários estágios .
FROM node:10-alpine AS base COPY client /portgen/client COPY server /portgen/server WORKDIR /portgen RUN cd client && npm i && npm run build FROM node:10-alpine WORKDIR /portgen COPY server/index.js /portgen/index.js COPY server/package.json /portgen/package.json COPY
Ou seja, no primeiro contêiner, execute "npm run build" e, no segundo contêiner, copie os arquivos de "dist" para "public". No final, temos uma imagem de 95mb.
Agora, temos uma imagem do docker que eu carreguei no hub.docker.com .
Lançamento
Agora queremos executar esta imagem no kubernetes'e, além disso, precisamos de um token que possa ver quais portas já estão sendo usadas via kubernetes api.
Para fazer isso, você precisa criar uma conta de servidor , uma função (você pode usar uma existente) e uma ligação de rolagem (não sei como traduzir corretamente).
Eu já tenho uma função de cluster "visualizar" no cluster
ceku@ceku1> kubectl describe clusterrole view Name: view Labels: kubernetes.io/bootstrapping=rbac-defaults Annotations: rbac.authorization.kubernetes.io/autoupdate=true PolicyRule: Resources Non-Resource URLs Resource Names Verbs --------- ----------------- -------------- ----- bindings [] [] [get list watch] configmaps [] [] [get list watch] endpoints [] [] [get list watch] events [] [] [get list watch] limitranges [] [] [get list watch] namespaces [] [] [get list watch] namespaces/status [] [] [get list watch] persistentvolumeclaims [] [] [get list watch] pods [] [] [get list watch] pods/log [] [] [get list watch] pods/status [] [] [get list watch] replicationcontrollers [] [] [get list watch] replicationcontrollers/scale [] [] [get list watch] replicationcontrollers/status [] [] [get list watch] resourcequotas [] [] [get list watch] resourcequotas/status [] [] [get list watch] serviceaccounts [] [] [get list watch] services [] [] [get list watch] daemonsets.apps [] [] [get list watch] deployments.apps [] [] [get list watch] deployments.apps/scale [] [] [get list watch] replicasets.apps [] [] [get list watch] replicasets.apps/scale [] [] [get list watch] statefulsets.apps [] [] [get list watch] horizontalpodautoscalers.autoscaling [] [] [get list watch] cronjobs.batch [] [] [get list watch] jobs.batch [] [] [get list watch] daemonsets.extensions [] [] [get list watch] deployments.extensions [] [] [get list watch] deployments.extensions/scale [] [] [get list watch] ingresses.extensions [] [] [get list watch] networkpolicies.extensions [] [] [get list watch] replicasets.extensions [] [] [get list watch] replicasets.extensions/scale [] [] [get list watch] replicationcontrollers.extensions/scale [] [] [get list watch] networkpolicies.networking.k8s.io [] [] [get list watch] poddisruptionbudgets.policy [] [] [get list watch]
Agora crie uma conta e role-binding
account_portng.yml:
apiVersion: v1 kind: ServiceAccount metadata: name: portng-service-get namespace: internal labels: k8s-app: portng-service-get kubernetes.io/cluster-service: "true"
rolebindng_portng.yml:
kind: ClusterRoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: namespace: internal name: view labels: k8s-app: portng-service-get kubernetes.io/cluster-service: "true" addonmanager.kubernetes.io/mode: Reconcile subjects: - kind: ServiceAccount name: portng-service-get namespace: kube-system apiGroup: "" roleRef: kind: ClusterRole name: view apiGroup: ""
Agora temos uma conta e ele tem um token. Seu nome está escrito na conta:
ceku@ceku1 /a/r/aditointernprod.aditosoftware.local> kubectl get serviceaccount portng-service-get -n internal -o yaml apiVersion: v1 kind: ServiceAccount metadata: creationTimestamp: 2018-08-02T07:31:54Z labels: k8s-app: portng-service-get kubernetes.io/cluster-service: "true" name: portng-service-get namespace: internal resourceVersion: "7270593" selfLink: /api/v1/namespaces/internal/serviceaccounts/portng-service-get uid: 2153dfa0-9626-11e8-aaa3-ac1f6b664c1c secrets: - name: portng-service-get-token-vr5bj
Agora você só precisa escrever a implantação, o serviço e a entrada para a página. Vamos começar:
deploy_portng.yml
apiVersion: apps/v1beta1 # for versions before 1.6.0 use extensions/v1beta1 kind: Deployment metadata: namespace: internal name: portng.server.local spec: replicas: 1 template: metadata: labels: app: portng.server.local spec: serviceAccountName: portng-service-get containers: - name: portgen image: de1m/k8s-nodeport-gen env: - name: K8SURL value: ceku.server.local - name: K8SPORT value: '6443' - name: K8STIMEOUT value: '30' - name: RESSPATH value: '/api/v1/services' - name: K8SPORTSTART value: '30000' - name: K8SPORTEND value: '32000' - name: PORT value: '8080' args: - /bin/sh - -c - export K8STOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token) && node /portgen/index.js
Há duas coisas a serem observadas: "serviceAccountName: portng-service-get" e o token para kubernetes, ou melhor, da maneira como eu o adicionei.
Agora vamos escrever um serviço:
svc_portng.yml
apiVersion: v1 kind: Service metadata: name: portng-server-local namespace: internal spec: ports: - name: http port: 8080 targetPort: 8080 selector: app: portng.server.local
E ingresso, para isso você deve ter um controlador de ingresso instalado
ingress_portng.yaml:
apiVersion: extensions/v1beta1 kind: Ingress metadata: name: portng.aditosoftware.local namespace: internal annotations: kubernetes.io/ingress.class: "internal" spec: rules: - host: portng.server.local http: paths: - path: / backend: serviceName: portng-server-local servicePort: 8080
Tudo, resta apenas fazer upload de arquivos para o servidor e executar.
Tudo isso pode ser iniciado como um contêiner de docker e mesmo sem ele, mas a parte com contas no kubernetes'e ainda terá que passar.
Recursos:
Imagem do Docker em hub.docker.com
Repositório Git no github.com
Como você pode ver, não há nada de especial neste artigo, mas para alguns acho que será interessante.