
Dies ist eine kurze Anmerkung zum Packen einer vue.js-Anwendung in eine Docker-Datei und zum Ausführen in einem Container in kubernetes'e.
Was macht
Ich habe ein kleines Programm geschrieben , das eine kostenlose NodePort- Nummer generiert. Eigentlich macht sie nichts besonders Nützliches, aber Sie müssen sich nicht mit der Suche nach einem Hafen beschäftigen und sehen zum Spaß, wie dies gemacht werden kann.
Gestartet
Das gesamte Projekt besteht aus zwei Teilen - Frontend und Server. Das Front-End fragt nach nodePort des Servers, und die Serverseite findet über die Kubernetes-API einige freie.
Damit dies im Docker funktioniert, müssen Sie einige Variablen aus der Anwendung extrahieren, z. B. die Adresse kubernetes api, port, token usw.
Es sieht so aus:
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)
Nehmen wir an, alles wird getestet und unsere Anwendung funktioniert.
Erstellen Sie ein Docker-Image
Diejenigen, die mit vue.js gearbeitet haben, wissen, dass es viele Arten von Dateien gibt, für die sie alle benötigt werden. Ich weiß nicht, aber sie müssen gesehen werden. Aber dank der Tatsache, dass es so etwas wie Vue-Cli gibt, kann alles ganz einfach verpackt werden. Jetzt packen wir alles:
npm run build
Danach haben wir den Ordner "dist" und die Datei "index.html" in "k8s-nodeport-gen / client". Und für die Arbeit brauchen wir nur sie. Das heißt, theoretisch benötigen Sie eine Art http-Server, damit das Frontend funktioniert. In diesem Fall gibt es aber auch ein Backend, das auch funktionieren sollte. Daher funktioniert in meinem Fall als http-Server node.js express.
Die Dateien werden später im Ordner k8s-nodeport-gen / public gespeichert. Fügen Sie dazu die Option zu server / index.js hinzu
app.use(express.static(__dirname + '/public'))
Nachdem Sie die Dateien analysiert haben, können Sie eine Docker-Datei erstellen. Wir vom Frontend müssen nur Dateien für den Ordner "dist" erstellen. Um dies zu tun, werden wir so etwas Neues als mehrstufigen Build verwenden .
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
Führen Sie im ersten Container "npm run build" aus und kopieren Sie im zweiten Container die Dateien von "dist" nach "public". Am Ende erhalten wir ein Bild von 95 MB.
Jetzt haben wir ein Docker-Image, das ich auf hub.docker.com hochgeladen habe .
Starten
Jetzt wollen wir dieses Image in kubernetes'e ausführen. Außerdem benötigen wir ein Token, das über kubernetes api sehen kann, welche Ports bereits verwendet werden.
Dazu müssen Sie ein Serverkonto , eine Rolle (Sie können ein vorhandenes verwenden) und eine Rollenbindung (ich weiß nicht, wie man richtig übersetzt) erstellen.
Ich habe bereits eine Clusterrolle "Ansicht" im 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]
Erstellen Sie nun ein Konto und eine Rollenbindung
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: ""
Jetzt haben wir einen Account und er hat einen Token. Sein Name steht im Konto:
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
Jetzt müssen Sie nur noch die Bereitstellung, den Service und den Eingang für die Seite schreiben. Fangen wir an:
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
Es gibt zwei Dinge zu beachten: "serviceAccountName: portng-service-get" und das Token für Kubernetes, oder besser gesagt, wie ich es hinzugefügt habe.
Jetzt schreiben wir einen Service:
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
Und Ingress, dafür muss ein Ingress-Controller installiert sein
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
Alles, es bleibt nur, Dateien auf den Server hochzuladen und auszuführen.
All dies kann sowohl als Docker-Container als auch ohne diesen gestartet werden, aber der Teil mit Konten in kubernetes'e muss noch durchlaufen werden.
Ressourcen:
Docker-Image unter hub.docker.com
Git-Repository auf github.com
Wie Sie sehen können, gibt es in diesem Artikel nichts Besonderes, aber für einige denke ich, dass es interessant sein wird.