Читать книгу K8s Applications mit MicroK8S auf Raspberry PI - Alfred Sabitzer - Страница 13
ОглавлениеEinfacher WebServer mit Go
Inspiration:
https://golang.org/doc/articles/wiki/
https://www.freecodecamp.org/news/how-to-remove-images-in-docker/
https://docs.docker.com/engine/reference/commandline/image_pull/
Dieses Kapitel beschreibt einen einfachen WebServer mit Go. Das ist ein richtig funktionierender WebService. Dieser Service wird alle Variablen und die Systemzeit des Containers wiedergeben.
Zuerst brauchen wir ein einfaches Programm.
// Ausgabe eines einfachen HTML-Files und ersetzen von Schlüsselwörtern mit konkreten Informationen
// Inspiration https://golang.org/doc/articles/wiki/
// https://www.socketloop.com/tutorials/golang-get-hardware-information-such-as-disk-memory-and-cpu-usage
//
// alfred@monitoring:~/GetInfo$ go get github.com/shirou/gopsutil/...
package main
import (
"bufio"
"fmt"
"io/ioutil"
"log"
"net/http"
"os"
"runtime"
"strconv"
"strings"
"time"
"github.com/shirou/gopsutil/disk"
"github.com/shirou/gopsutil/host"
"github.com/shirou/gopsutil/mem"
)
type Page struct {
Title string
Body []byte
}
func loadError(xerr string) (xhtml string) {
var xs string
currentTime := time.Now()
xtext, err := ioutil.ReadFile("error.html")
if err != nil {
log.Fatal("Error File kann nicht geöffnet werden " + err.Error())
}
xs = strings.Replace(string(xtext), "%SYSTIME%", currentTime.Format("2006-01-02 15:04:05 Monday"), -1)
xs = strings.Replace(string(xs), "%SYSTEMFEHLER%", xerr, -1)
return xs
}
func loadPage(title string) (*Page, error) {
var xhtml string
var xtmp string
var xenv string
const GB = 1073741824
filename := title + ".html"
log.Println(filename)
xhtml = ""
currentTime := time.Now()
f, err := os.Open(filename)
if err != nil {
log.Println(filename+" kann nicht geöffnet werden: ", err)
xhtml = loadError(err.Error())
} else {
scanner := bufio.NewScanner(f)
for scanner.Scan() {
xtmp = scanner.Text()
if strings.Contains(xtmp, "%SYSTIME%") {
xtmp = strings.Replace(xtmp, "%SYSTIME%", currentTime.Format("2006-01-02 15:04:05 Monday"), -1)
}
if strings.Contains(xtmp, "%OSENVIRONMENT%") {
xenv = ""
for _, pair := range os.Environ() {
variable := strings.Split(pair, "=")
xenv += variable[0] + "=>" + variable[1] + "<br>"
}
xtmp = strings.Replace(xtmp, "%OSENVIRONMENT%", xenv, -1)
}
if strings.Contains(xtmp, "%DISKUSAGE%") {
diskStat, err := disk.Usage("/")
if err != nil {
log.Println(" Plattenbelegung kann nicht gelesen werden: ", err)
}
xenv = "Pfad:" + diskStat.Path +
"<br>FSTYPE:" + diskStat.Fstype +
"<br>Total disk space:" + fmt.Sprintf("%5.1f", float64(diskStat.Total)/GB) +
" GB<br>Free disk space:" + fmt.Sprintf("%5.1f", float64(diskStat.Free)/GB) +
" GB<br>Used disk space:" + fmt.Sprintf("%5.1f", float64(diskStat.Used)/GB) +
" GB<br>Used GB Prozent:" + fmt.Sprintf("%3.1f", diskStat.UsedPercent) +
"<br>Used Inodes:" + strconv.FormatUint(diskStat.InodesUsed, 10) +
"<br>Used Inodes Prozent:" + fmt.Sprintf("%3.1f", diskStat.InodesUsedPercent)
xtmp = strings.Replace(xtmp, "%DISKUSAGE%", xenv, -1)
}
if strings.Contains(xtmp, "%HOSTINFO%") {
// host or machine kernel, uptime, platform Info
hostStat, err := host.Info()
if err != nil {
log.Println(" Hostinformation kann nicht gelesen werden: ", err)
}
xenv = "Hostname: " + hostStat.Hostname +
"<br>OS: " + hostStat.OS +
"<br>Platform: " + hostStat.Platform +
"<br>Host ID(uuid): " + hostStat.HostID +
"<br>Uptime (sec): " + strconv.FormatUint(hostStat.Uptime, 10) +
"<br>Number of processes running: " + strconv.FormatUint(hostStat.Procs, 10)
xtmp = strings.Replace(xtmp, "%HOSTINFO%", xenv, -1)
}
if strings.Contains(xtmp, "%MEMINFO%") {
runtimeOS := runtime.GOOS
vmStat, err := mem.VirtualMemory()
if err != nil {
log.Println(" Memoryinformation kann nicht gelesen werden: ", err)
}
xenv = "OS : " + runtimeOS +
"<br>Total memory: " + fmt.Sprintf("%5.1f", float64(vmStat.Total)/GB) +
" GB<br>Free memory: " + fmt.Sprintf("%5.1f", float64(vmStat.Free)/GB) +
" GB<br>Used memory: " + fmt.Sprintf("%5.1f", float64(vmStat.Used)/GB) +
" GB<br>Percentage used memory: " + strconv.FormatFloat(vmStat.UsedPercent, 'f', 2, 64)
xtmp = strings.Replace(xtmp, "%MEMINFO%", xenv, -1)
}
xhtml += xtmp
}
if err := scanner.Err(); err != nil {
log.Println(filename+" kann nicht gelesen werden: %s\n", err)
xhtml = loadError(err.Error())
}
}
defer f.Close()
return &Page{Title: title, Body: []byte(xhtml)}, nil
}
func viewHandler(w http.ResponseWriter, r *http.Request) {
title := r.URL.Path[len("/view/"):]
p, _ := loadPage(title)
fmt.Fprintf(w, "%s", p.Body)
}
func main() {
log.Println("Main Started")
http.HandleFunc("/view/", viewHandler)
log.Fatal(http.ListenAndServe(":8080", nil))
log.Println("Main End")
}
Um die Abhängigkeiten richtig auflösen zu können, braucht go auch ein module-File. Diese Dateien werden vom SDK LiteIDE selbstständig erzeugt.
alfred@monitoring:~/GetInfo$ cat go.mod
module GetInfo
go 1.16
require (
github.com/StackExchange/wmi v1.2.1 // indirect
github.com/shirou/gopsutil v3.21.9+incompatible // indirect
github.com/tklauser/go-sysconf v0.3.9 // indirect
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac // indirect
)
alfred@monitoring:~/GetInfo$ cat go.sum
github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA=
github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8=
github.com/go-ole/go-ole v1.2.5 h1:t4MGB5xEDZvXI+0rMjjsfBsD7yAgp/s9ZDkL1JndXwY=
github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/shirou/gopsutil v3.21.9+incompatible h1:LTLpUnfX81MkHeCtSrwNKZwuW5Id6kCa7/P43NdcNn4=
github.com/shirou/gopsutil v3.21.9+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
github.com/tklauser/go-sysconf v0.3.9 h1:JeUVdAOWhhxVcU6Eqr/ATFHgXk/mmiItdKeJPev3vTo=
github.com/tklauser/go-sysconf v0.3.9/go.mod h1:11DU/5sG7UexIrp/O6g35hrWzu0JxlwQ3LSFUzyeuhs=
github.com/tklauser/numcpus v0.3.0 h1:ILuRUQBtssgnxw0XXIjKUC56fgnOrFoQQ/4+DeU2biQ=
github.com/tklauser/numcpus v0.3.0/go.mod h1:yFGUr7TUHQRAhyqBcEg0Ge34zDBAsIvJJcyE6boqnA8=
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210816074244-15123e1e1f71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac h1:oN6lz7iLW/YC7un8pq+9bOLyXrprv2+DKfkJY+2LJJw=
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
alfred@monitoring:~/GetInfo$
Dieses Programm zeigt nach dem Aufruf von <Link:8080/view/filename> das aufgerufene File <filename> an, und ersetzt gewisse Schlüsselwörter durch konkreten Text. In unserem Beispiel habe ich das File hello.html mit OpenOffice vorbereitet.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
<title></title>
<meta name="generator" content="LibreOffice 7.1.6.2 (Linux)"/>
<meta name="author" content="Alfred Sabitzer"/>
<meta name="created" content="2021-10-07T16:33:50.696105947"/>
<meta name="changedby" content="Alfred Sabitzer"/>
<meta name="changed" content="2021-10-07T16:36:08.816466992"/>
<style type="text/css">
@page { size: 21cm 29.7cm; margin: 2cm }
p { margin-bottom: 0.25cm; line-height: 115%; background: transparent }
td p { orphans: 0; widows: 0; background: transparent }
</style>
</head>
<body lang="de-AT" link="#000080" vlink="#800000" dir="ltr"><p style="margin-bottom: 0cm; line-height: 100%">
<p style="margin-bottom: 0cm; line-height: 100%"><br/>
</p>
<table width="100%" cellpadding="4" cellspacing="0">
<col width="64*"/>
<col width="64*"/>
<col width="64*"/>
<col width="64*"/>
<tr valign="top">
<td width="25%" style="border-top: 1px solid #000000; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0.1cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm"><p>
OSENVIRONMENT</p>
</td>
<td width="25%" style="border-top: 1px solid #000000; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0.1cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm"><p>
DISKUSAGE</p>
</td>
<td width="25%" style="border-top: 1px solid #000000; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0.1cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm"><p>
HOSTINFO</p>
</td>
<td width="25%" style="border: 1px solid #000000; padding: 0.1cm"><p>
MEMINFO</p>
</td>
</tr>
<tr valign="top">
<td width="25%" style="border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm"><p>
%OSENVIRONMENT%
</p>
</td>
<td width="25%" style="border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm"><p>
%DISKUSAGE%
</p>
</td>
<td width="25%" style="border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm"><p>
%HOSTINFO%</p>
</td>
<td width="25%" style="border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0.1cm"><p>
%MEMINFO%</p>
</td>
</tr>
</table>
<p style="margin-bottom: 0cm; line-height: 100%"><br/>
</p>
<p style="margin-bottom: 0cm; line-height: 100%">Es ist <span style="background: #c0c0c0"><sdfield type=DATETIME sdval="44476,6908896088" sdnum="3079;3079;T. MMMM JJJJ">%SYSTIME%</sdfield></span></p>
</body>
</html>
Nun kompilieren wir das File.
alfred@monitoring:~/GetInfo$ go build GetInfo.go
go: downloading github.com/shirou/gopsutil v3.21.9+incompatible
go: extracting github.com/shirou/gopsutil v3.21.9+incompatible
go: downloading golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac
go: extracting golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac
go: finding github.com/shirou/gopsutil v3.21.9+incompatible
go: finding golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac
alfred@monitoring:~/GetInfo$ ll
total 7716
drwxrwxr-x 2 alfred alfred 4096 Oct 15 20:30 ./
drwxr-xr-x 22 alfred alfred 4096 Oct 11 07:30 ../
-rwxrwxr-x 1 alfred alfred 8009715 Oct 15 20:30 GetInfo*
-rw------- 1 alfred alfred 4473 Oct 10 21:34 GetInfo.go
-rw------- 1 alfred alfred 81 Oct 10 21:48 dockerfile
-rw------- 1 alfred alfred 1434 Oct 10 21:19 error.html
-rw-rw-r-- 1 alfred alfred 0 Oct 11 07:28 getinfo.tar
-rw------- 1 alfred alfred 263 Oct 10 10:04 go.mod
-rw------- 1 alfred alfred 1314 Oct 10 10:04 go.sum
-rw------- 1 alfred alfred 3180 Oct 10 21:32 hello.html
alfred@monitoring:~/GetInfo$ ./GetInfo
Ein kurzer Test auf http://monitoring:8080/view/hello ergibt
Abbildung 20: GetInfo Ausgabe
Das heist das Programm funktioniert. Die Logausgabe sieht aus wie folgt:
alfred@monitoring:~/GetInfo$ ./GetInfo
2021/10/10 21:42:01 Main Started
2021/10/10 21:42:16 hello.html
^C
alfred@monitoring:~/GetInfo$
Jetzt brauchen wir noch ein Docker-File
alfred@monitoring:~/GetInfo$ cat dockerfile
# syntax=docker/dockerfile:1
# Alpine is chosen for its small footprint
# compared to Ubuntu
FROM golang:1.16-alpine
WORKDIR /app
# Download necessary Go modules
COPY go.mod ./
COPY go.sum ./
RUN go mod download
COPY *.go ./
COPY hello.html ./
COPY error.html ./
RUN go build -o /GetInfo
EXPOSE 8080
CMD [ "/GetInfo" ]
alfred@monitoring:~/GetInfo$
um den Container zu bauen.
alfred@monitoring:~/GetInfo$ docker build . -t docker.registry:5000/getinfo:20211015
Sending build context to Docker daemon 16.38kB
Step 1/11 : FROM golang:1.16-alpine
1.16-alpine: Pulling from library/golang
552d1f2373af: Pull complete
eb74239f2a0c: Pull complete
2a8ec004bf6b: Pull complete
12f1fa1a3b20: Pull complete
5c12166b7f9d: Pull complete
Digest: sha256:05df7ff684a2cb06aa207be14a78918cbc3285ed3b965974979e575d59de1c11
Status: Downloaded newer image for golang:1.16-alpine
---> d2f4346f5656
Step 2/11 : WORKDIR /app
---> Running in 9b6c3b098321
Removing intermediate container 9b6c3b098321
---> 738bd59f63db
Step 3/11 : COPY go.mod ./
---> cb6306d5fdf2
Step 4/11 : COPY go.sum ./
---> f7eeef9ebda2
Step 5/11 : RUN go mod download
---> Running in efbe89b22883
Removing intermediate container efbe89b22883
---> cb738e90d4d7
Step 6/11 : COPY *.go ./
---> c5ab2f4e9e5c
Step 7/11 : COPY hello.html ./
---> 8e6738e25799
Step 8/11 : COPY error.html ./
---> 5c9506b2dc3f
Step 9/11 : RUN go build -o /GetInfo.go
---> Running in 3ad675aeb626
Removing intermediate container 3ad675aeb626
---> 0abfe5a9d849
Step 10/11 : EXPOSE 8080
---> Running in 80f728420378
Removing intermediate container 80f728420378
---> b9c5a76c55d2
Step 11/11 : CMD [ "/GetInfo" ]
---> Running in 71d6f27934d2
Removing intermediate container 71d6f27934d2
---> 4fae231152c2
Successfully built 4fae231152c2
Successfully tagged docker.registry:5000/getinfo:20211015
alfred@monitoring:~/GetInfo$
alfred@monitoring:~/GetInfo$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker.registry:5000/getinfo 20211015 4fae231152c2 39 seconds ago 317MB
golang 1.16-alpine d2f4346f5656 2 days ago 296MB
alfred@monitoring:~/GetInfo$
Nun starten wir den Container im Vordergrund um den Output zu testen.
alfred@monitoring:~/GetInfo$ docker run --publish 8080:8080 docker.registry:5000/getinfo:20211015
2021/10/15 19:22:13 Main Started
2021/10/15 19:22:40 hello.html
Der Output im Browser ist wie folgt:
Abbildung 21: Docker Test Output
Der Container ist am erwarteten Port erreichbar. Die Anzeige der Werte sind jetzt aus Sicht des Containers, wie man an den Variablen und am Environment sehen kann.
Wir überprüfen die Struktur des gebauten docker-files.
alfred@monitoring:~/GetInfo$ docker save docker.registry:5000/getinfo:20211015 > getinfo.tar
alfred@monitoring:~/GetInfo$ tar -tvf getinfo.tar
-rw-r--r-- 0/0 7059 2021-10-15 21:22 0fca605bf404203fe0e1d41e306687bf70b8cdb4392c41363af0f6712ae28959.json
drwxr-xr-x 0/0 0 2021-10-15 21:22 11ada22ca4865de4368da5b2cdea81c34f3fc62b60e62f00329f839e1e51a431/
-rw-r--r-- 0/0 3 2021-10-15 21:22 11ada22ca4865de4368da5b2cdea81c34f3fc62b60e62f00329f839e1e51a431/VERSION
-rw-r--r-- 0/0 406 2021-10-15 21:22 11ada22ca4865de4368da5b2cdea81c34f3fc62b60e62f00329f839e1e51a431/json
-rw-r--r-- 0/0 5605376 2021-10-15 21:22 11ada22ca4865de4368da5b2cdea81c34f3fc62b60e62f00329f839e1e51a431/layer.tar
drwxr-xr-x 0/0 0 2021-10-15 21:22 1a41da37655e1ae130db0ff268801f26989f408ad4e24fee81b18252883fe835/
-rw-r--r-- 0/0 3 2021-10-15 21:22 1a41da37655e1ae130db0ff268801f26989f408ad4e24fee81b18252883fe835/VERSION
-rw-r--r-- 0/0 482 2021-10-15 21:22 1a41da37655e1ae130db0ff268801f26989f408ad4e24fee81b18252883fe835/json
-rw-r--r-- 0/0 2560 2021-10-15 21:22 1a41da37655e1ae130db0ff268801f26989f408ad4e24fee81b18252883fe835/layer.tar
drwxr-xr-x 0/0 0 2021-10-15 21:22 278bc14dbdd9bd52e524b98375e76f5b0f975f02167b6a7e8168184e577a8d17/
-rw-r--r-- 0/0 3 2021-10-15 21:22 278bc14dbdd9bd52e524b98375e76f5b0f975f02167b6a7e8168184e577a8d17/VERSION
-rw-r--r-- 0/0 482 2021-10-15 21:22 278bc14dbdd9bd52e524b98375e76f5b0f975f02167b6a7e8168184e577a8d17/json
-rw-r--r-- 0/0 5632 2021-10-15 21:22 278bc14dbdd9bd52e524b98375e76f5b0f975f02167b6a7e8168184e577a8d17/layer.tar
drwxr-xr-x 0/0 0 2021-10-15 21:22 37df72a20bd40f12a164a419626ffb20b4554c96983ec36b78024136e65f15c2/
-rw-r--r-- 0/0 3 2021-10-15 21:22 37df72a20bd40f12a164a419626ffb20b4554c96983ec36b78024136e65f15c2/VERSION
-rw-r--r-- 0/0 482 2021-10-15 21:22 37df72a20bd40f12a164a419626ffb20b4554c96983ec36b78024136e65f15c2/json
-rw-r--r-- 0/0 2560 2021-10-15 21:22 37df72a20bd40f12a164a419626ffb20b4554c96983ec36b78024136e65f15c2/layer.tar
drwxr-xr-x 0/0 0 2021-10-15 21:22 55a816cb614fc0754c9af49269934861de9251688789bc4a3e9f304ac1059e10/
-rw-r--r-- 0/0 3 2021-10-15 21:22 55a816cb614fc0754c9af49269934861de9251688789bc4a3e9f304ac1059e10/VERSION
-rw-r--r-- 0/0 482 2021-10-15 21:22 55a816cb614fc0754c9af49269934861de9251688789bc4a3e9f304ac1059e10/json
-rw-r--r-- 0/0 3584 2021-10-15 21:22 55a816cb614fc0754c9af49269934861de9251688789bc4a3e9f304ac1059e10/layer.tar
drwxr-xr-x 0/0 0 2021-10-15 21:22 5fe6d80a697427a6b315445103e12f8e5e14a6f9f071e119d9da5aa7787dedf0/
-rw-r--r-- 0/0 3 2021-10-15 21:22 5fe6d80a697427a6b315445103e12f8e5e14a6f9f071e119d9da5aa7787dedf0/VERSION
-rw-r--r-- 0/0 1432 2021-10-15 21:22 5fe6d80a697427a6b315445103e12f8e5e14a6f9f071e119d9da5aa7787dedf0/json
-rw-r--r-- 0/0 10244608 2021-10-15 21:22 5fe6d80a697427a6b315445103e12f8e5e14a6f9f071e119d9da5aa7787dedf0/layer.tar
drwxr-xr-x 0/0 0 2021-10-15 21:22 678b476f25ed3f1e67caefc50b99dba99e907d2b692e7198f4f7982b1781dd97/
-rw-r--r-- 0/0 3 2021-10-15 21:22 678b476f25ed3f1e67caefc50b99dba99e907d2b692e7198f4f7982b1781dd97/VERSION
-rw-r--r-- 0/0 482 2021-10-15 21:22 678b476f25ed3f1e67caefc50b99dba99e907d2b692e7198f4f7982b1781dd97/json
-rw-r--r-- 0/0 297840128 2021-10-15 21:22 678b476f25ed3f1e67caefc50b99dba99e907d2b692e7198f4f7982b1781dd97/layer.tar
drwxr-xr-x 0/0 0 2021-10-15 21:22 916863cb53dae4e13619f82e13ddeded5a2a2f552e5ac0fad747eff6cafe57ea/
-rw-r--r-- 0/0 3 2021-10-15 21:22 916863cb53dae4e13619f82e13ddeded5a2a2f552e5ac0fad747eff6cafe57ea/VERSION
-rw-r--r-- 0/0 482 2021-10-15 21:22 916863cb53dae4e13619f82e13ddeded5a2a2f552e5ac0fad747eff6cafe57ea/json
-rw-r--r-- 0/0 2048 2021-10-15 21:22 916863cb53dae4e13619f82e13ddeded5a2a2f552e5ac0fad747eff6cafe57ea/layer.tar
drwxr-xr-x 0/0 0 2021-10-15 21:22 951da7c93bcb5858e3370883aa7ebb5bc7e54ad5a51a9124350c4bf638dfce39/
-rw-r--r-- 0/0 3 2021-10-15 21:22 951da7c93bcb5858e3370883aa7ebb5bc7e54ad5a51a9124350c4bf638dfce39/VERSION
-rw-r--r-- 0/0 482 2021-10-15 21:22 951da7c93bcb5858e3370883aa7ebb5bc7e54ad5a51a9124350c4bf638dfce39/json
-rw-r--r-- 0/0 3584 2021-10-15 21:22 951da7c93bcb5858e3370883aa7ebb5bc7e54ad5a51a9124350c4bf638dfce39/layer.tar
drwxr-xr-x 0/0 0 2021-10-15 21:22 c738b6de5b0a35e613204439d94e3142a49ed7c77568b1372a2ac8e44add5431/
-rw-r--r-- 0/0 3 2021-10-15 21:22 c738b6de5b0a35e613204439d94e3142a49ed7c77568b1372a2ac8e44add5431/VERSION
-rw-r--r-- 0/0 482 2021-10-15 21:22 c738b6de5b0a35e613204439d94e3142a49ed7c77568b1372a2ac8e44add5431/json
-rw-r--r-- 0/0 759808 2021-10-15 21:22 c738b6de5b0a35e613204439d94e3142a49ed7c77568b1372a2ac8e44add5431/layer.tar
drwxr-xr-x 0/0 0 2021-10-15 21:22 d0cabd374001156bcc1eb54fb096bcb80aa5f94e14ed6c73069b64e31f554deb/
-rw-r--r-- 0/0 3 2021-10-15 21:22 d0cabd374001156bcc1eb54fb096bcb80aa5f94e14ed6c73069b64e31f554deb/VERSION
-rw-r--r-- 0/0 482 2021-10-15 21:22 d0cabd374001156bcc1eb54fb096bcb80aa5f94e14ed6c73069b64e31f554deb/json
-rw-r--r-- 0/0 11713024 2021-10-15 21:22 d0cabd374001156bcc1eb54fb096bcb80aa5f94e14ed6c73069b64e31f554deb/layer.tar
drwxr-xr-x 0/0 0 2021-10-15 21:22 e3c9af4387b692800410b9c839fd7964352a56504f884d7975fff36dc077c8c4/
-rw-r--r-- 0/0 3 2021-10-15 21:22 e3c9af4387b692800410b9c839fd7964352a56504f884d7975fff36dc077c8c4/VERSION
-rw-r--r-- 0/0 482 2021-10-15 21:22 e3c9af4387b692800410b9c839fd7964352a56504f884d7975fff36dc077c8c4/json
-rw-r--r-- 0/0 6656 2021-10-15 21:22 e3c9af4387b692800410b9c839fd7964352a56504f884d7975fff36dc077c8c4/layer.tar
drwxr-xr-x 0/0 0 2021-10-15 21:22 eb528dd90d9b2bc0ad36512a3ce210982ca2b2100be249c54335bb4c86b6c520/
-rw-r--r-- 0/0 3 2021-10-15 21:22 eb528dd90d9b2bc0ad36512a3ce210982ca2b2100be249c54335bb4c86b6c520/VERSION
-rw-r--r-- 0/0 482 2021-10-15 21:22 eb528dd90d9b2bc0ad36512a3ce210982ca2b2100be249c54335bb4c86b6c520/json
-rw-r--r-- 0/0 2560 2021-10-15 21:22 eb528dd90d9b2bc0ad36512a3ce210982ca2b2100be249c54335bb4c86b6c520/layer.tar
-rw-r--r-- 0/0 1151 1970-01-01 01:00 manifest.json
-rw-r--r-- 0/0 114 1970-01-01 01:00 repositories
alfred@monitoring:~/GetInfo$ ll *.tar
-rw-rw-r-- 1 alfred alfred 326244864 Oct 15 21:27 getinfo.tar
alfred@monitoring:~/GetInfo$
Wir können aber auch das Dockerfile selbst exportieren.
alfred@monitoring:~/GetInfo$ docker ps -all
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
acdf3516a1ce docker.registry:5000/getinfo:20211015 "/GetInfo" 10 minutes ago Exited (2) 5 minutes ago funny_keller
alfred@monitoring:~/GetInfo$ docker export acdf3516a1ce > getinfo.tar
alfred@monitoring:~/GetInfo$
alfred@monitoring:~/GetInfo$ ll -h *.tar
-rw-rw-r-- 1 alfred alfred 311M Oct 15 21:32 getinfo.tar
alfred@monitoring:~/GetInfo$
alfred@monitoring:~/GetInfo$ tar -tvf getinfo.tar
Mit diesen Befehlen kann man überprüfen was alles im Container drinnenn ist (und das ist eine ganze Menge).
Nun pushen wir den Container in das remote-Repository. Es werden natürlich alle Layer gepushed (in dem Falle gab es die darunterliegenden Layer noch nicht).
alfred@monitoring:~/GetInfo$ docker push docker.registry:5000/getinfo:20211015
The push refers to repository [docker.registry:5000/getinfo]
cae68116d3ec: Pushed
dd68a1e5bd54: Pushed
00e2dc9bf745: Pushed
5a8d0b1f55c0: Pushed
8f352be1ccfe: Pushed
729e17fedb70: Pushed
08ae3e8fdb37: Pushed
6fe1ba639418: Pushed
fa0d2ce7179e: Pushed
092886e29cb5: Pushed
c8d42fc353a6: Pushed
6a91c97933c9: Pushed
ee420dfed78a: Pushed
20211015: digest: sha256:aa82ba777936d4cec354c0b9c5ece353751a96c9717375cfd58d3ed2beea5cf4 size: 3030
alfred@monitoring:~/GetInfo$
Kurze Kontrolle, ob der Container wirklich im Remote Repository gelandet ist.
alfred@monitoring:~/GetInfo$ curl docker.registry:5000/v2/_catalog
{"repositories":["getinfo","hello-world"]}
alfred@monitoring:~/GetInfo$ curl docker.registry:5000/v2/getinfo/tags/list
{"name":"getinfo","tags":["20211015"]}
alfred@monitoring:~/GetInfo$
Abbildung 22: Longhorn Plattengröße
Auch in der Longhorn-Anzeige kann man schön sehen, dass dieses Volume nicht mehr leer ist, und jetzt bereits ca. 1GB Platz braucht.
Nun erzeugen wir ein yaml-File.
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: getinfo
#namespace: default
spec:
selector:
matchLabels:
app: getinfo
replicas: 1
template:
metadata:
labels:
app: getinfo
annotations:
sidecar.istio.io/inject: "false"
spec:
containers:
- name: getinfo
image: docker.registry:5000/getinfo:20211015
# resource limits
resources:
requests:
memory: "24Mi"
cpu: "500m" # half vcpu
limits:
memory: "64Mi"
cpu: "1000m" # one vcpu
env:
# currently no env vars used for this container
- name: FOO
value: bar
# check for lifetime liveness, restarts if dead
livenessProbe:
exec:
command:
- ls
initialDelaySeconds: 5
periodSeconds: 10
# check for initial readyness
readinessProbe:
exec:
command:
- ls
initialDelaySeconds: 3
periodSeconds: 3
# pod bekommt diesselbe Zeitzone wie der darunterliegende Node
volumeMounts:
- name: tz-local
mountPath: /etc/localtime
volumes:
- name: tz-local
hostPath: # abhängig vom darunterliegenden OS. Das hier ist linux.
path: /etc/localtime
restartPolicy: Always
dnsPolicy: ClusterFirst
---
apiVersion: v1
kind: Service
metadata:
name: getinfo-service
#namespace: default
labels:
app: getinfo
spec:
ports:
# port=available to other containers
- port: 8080
name: hello
# targetPort=exposed from inside container
targetPort: 8080
protocol: TCP
selector:
app: getinfo
---
Dieses yaml wenden wir nun im Cluster an.
alfred@pc1:~$ k apply -f getinfo.yaml
deployment.apps/getinfo created
service/getinfo-service created
alfred@pc1:~$ kubectl get all
NAME READY STATUS RESTARTS AGE
pod/webserver-slainte-67494d5d7b-hj99r 1/1 Running 22 67d
pod/getinfo-6c84cff999-mtf5v 1/1 Running 0 89s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.152.183.1 <none> 443/TCP 67d
service/webserver-slainte ClusterIP 10.152.183.125 <none> 443/TCP 67d
service/getinfo-service ClusterIP 10.152.183.43 <none> 8080/TCP 6m12s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/webserver-slainte 1/1 1 1 67d
deployment.apps/getinfo 1/1 1 1 6m12s
NAME DESIRED CURRENT READY AGE
replicaset.apps/webserver-slainte-67494d5d7b 1 1 1 67d
replicaset.apps/getinfo-6c84cff999 1 1 1 89s
replicaset.apps/getinfo-6659cf7655 0 0 0 6m12s
Die Anzeige im Dashboard zeigt uns auch einen gut laufenden Pod.
Abbildung 23: GetInfo Pod im Dashboard
Nun schauen wir, was der Pod zurückliefert:
alfred@pc1:~$ curl http://10.152.183.43:8080/view/hello
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"><html><head> <meta http-equiv="content-type" content="text/html; charset=utf-8"/> <title></title> <meta name="generator" content="LibreOffice 7.1.6.2 (Linux)"/> <meta name="author" content="Alfred Sabitzer"/> <meta name="created" content="2021-10-07T16:33:50.696105947"/> <meta name="changedby" content="Alfred Sabitzer"/> <meta name="changed" content="2021-10-07T16:36:08.816466992"/> <style type="text/css"> @page { size: 21cm 29.7cm; margin: 2cm } p { margin-bottom: 0.25cm; line-height: 115%; background: transparent } td p { orphans: 0; widows: 0; background: transparent } </style></head><body lang="de-AT" link="#000080" vlink="#800000" dir="ltr"><p style="margin-bottom: 0cm; line-height: 100%"><p style="margin-bottom: 0cm; line-height: 100%"><br/></p><table width="100%" cellpadding="4" cellspacing="0"> <col width="64*"/> <col width="64*"/> <col width="64*"/> <col width="64*"/> <tr valign="top"> <td width="25%" style="border-top: 1px solid #000000; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0.1cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm"><p> OSENVIRONMENT</p> </td> <td width="25%" style="border-top: 1px solid #000000; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0.1cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm"><p> DISKUSAGE</p> </td> <td width="25%" style="border-top: 1px solid #000000; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0.1cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm"><p> HOSTINFO</p></td> <td width="25%" style="border: 1px solid #000000; padding: 0.1cm"><p> MEMINFO</p> </td> </tr> <tr valign="top"> <td width="25%" style="border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm"><p> PATH=>/go/bin:/usr/local/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin<br>HOSTNAME=>getinfo-6c84cff999-mtf5v<br>GOLANG_VERSION=>1.16.9<br>GOPATH=>/go<br>FOO=>bar<br>WEBSERVER_SLAINTE_PORT_443_TCP=>tcp://10.152.183.125:443<br>GETINFO_SERVICE_SERVICE_PORT=>8080<br>GETINFO_SERVICE_PORT=>tcp://10.152.183.43:8080<br>GETINFO_SERVICE_PORT_8080_TCP=>tcp://10.152.183.43:8080<br>GETINFO_SERVICE_PORT_8080_TCP_PROTO=>tcp<br>GETINFO_SERVICE_PORT_8080_TCP_ADDR=>10.152.183.43<br>WEBSERVER_SLAINTE_SERVICE_PORT=>443<br>WEBSERVER_SLAINTE_PORT=>tcp://10.152.183.125:443<br>KUBERNETES_SERVICE_HOST=>10.152.183.1<br>KUBERNETES_PORT=>tcp://10.152.183.1:443<br>KUBERNETES_PORT_443_TCP=>tcp://10.152.183.1:443<br>KUBERNETES_PORT_443_TCP_PORT=>443<br>WEBSERVER_SLAINTE_SERVICE_HOST=>10.152.183.125<br>WEBSERVER_SLAINTE_SERVICE_PORT_HTTPS=>443<br>WEBSERVER_SLAINTE_PORT_443_TCP_PROTO=>tcp<br>KUBERNETES_SERVICE_PORT=>443<br>KUBERNETES_PORT_443_TCP_PROTO=>tcp<br>GETINFO_SERVICE_SERVICE_PORT_HELLO=>8080<br>GETINFO_SERVICE_PORT_8080_TCP_PORT=>8080<br>WEBSERVER_SLAINTE_PORT_443_TCP_PORT=>443<br>WEBSERVER_SLAINTE_PORT_443_TCP_ADDR=>10.152.183.125<br>KUBERNETES_SERVICE_PORT_HTTPS=>443<br>KUBERNETES_PORT_443_TCP_ADDR=>10.152.183.1<br>GETINFO_SERVICE_SERVICE_HOST=>10.152.183.43<br>HOME=>/root<br> </p> </td><td width="25%" style="border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm"><p> Pfad:/<br>FSTYPE:<br>Total disk space: 58.3 GB<br>Free disk space: 46.1 GB<br>Used disk space: 9.7 GB<br>Used GB Prozent:17.4<br>Used Inodes:176202<br>Used Inodes Prozent:4.7 </p> </td> <td width="25%" style="border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm"><p> Hostname: getinfo-6c84cff999-mtf5v<br>OS: linux<br>Platform: alpine<br>Host ID(uuid): c1e70216-8eeb-4ca0-ac87-cf090dcc2c1f<br>Uptime (sec): 5085<br>Number of processes running: 1</p> </td> <td width="25%" style="border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0.1cm"><p> OS : linux<br>Total memory: 7.6 GB<br>Free memory: 3.1 GB<br>Used memory: 2.0 GB<br>Percentage used memory: 26.48</p> </td> </tr> </table><p style="margin-bottom: 0cm; line-height: 100%"><br/></p><p style="margin-bottom: 0cm; line-height: 100%">Es ist <span style="background: #c0c0c0"><sdfield type=DATETIME sdval="44476,6908896088" sdnum="3079;3079;T. MMMM JJJJ">2021-10-15 20:00:26 Friday</sdf
alfred@pc1:~$
Sieht ganz gut aus:) Auch der Logoutput ist interessant:
alfred@pc1:~$ kubectl logs getinfo-6c84cff999-mtf5v
2021/10/15 19:58:40 Main Started
2021/10/15 20:00:26 hello.html
alfred@pc1:~$
Um den Output richtig zu sehen, ändere ich zu Testzwecken den Typ des Services auf einen NodePort um den Service von außen erreichen zu können.
alfred@pc1:~$ kubectl edit service getinfo-service
service/getinfo-service edited
alfred@pc1:~$
alfred@pc1:~$ kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.152.183.1 <none> 443/TCP 67d
webserver-slainte ClusterIP 10.152.183.125 <none> 443/TCP 67d
getinfo-service NodePort 10.152.183.43 <none> 8080:32304/TCP 19m
alfred@pc1:~$
Der Output aus dem inneren des Pods sieht am Browser auch gut aus.
Abbildung 24: GetInfo Anzeige aus dem Pod
Somit haben wir einen richtigen Service im Kubernetes-Cluster laufen. Wir kontrollieren den Pod noch von innen.
alfred@pc1:~$ kubectl exec getinfo-6c84cff999-mtf5v -it -- /bin/sh
/app # df -h
Filesystem Size Used Available Use% Mounted on
overlay 58.3G 9.8G 46.1G 17% /
tmpfs 64.0M 0 64.0M 0% /dev
tmpfs 3.8G 0 3.8G 0% /sys/fs/cgroup
/dev/mmcblk0p2 58.3G 9.8G 46.1G 17% /etc/localtime
/dev/mmcblk0p2 58.3G 9.8G 46.1G 17% /etc/hosts
/dev/mmcblk0p2 58.3G 9.8G 46.1G 17% /dev/termination-log
/dev/mmcblk0p2 58.3G 9.8G 46.1G 17% /etc/hostname
/dev/mmcblk0p2 58.3G 9.8G 46.1G 17% /etc/resolv.conf
shm 64.0M 0 64.0M 0% /dev/shm
tmpfs 3.8G 12.0K 3.8G 0% /run/secrets/kubernetes.io/serviceaccount
tmpfs 64.0M 0 64.0M 0% /proc/kcore
tmpfs 64.0M 0 64.0M 0% /proc/keys
tmpfs 64.0M 0 64.0M 0% /proc/latency_stats
tmpfs 64.0M 0 64.0M 0% /proc/timer_list
tmpfs 64.0M 0 64.0M 0% /proc/sched_debug
tmpfs 3.8G 0 3.8G 0% /proc/scsi
tmpfs 3.8G 0 3.8G 0% /sys/firmware
/app # date
Sat Oct 16 09:31:11 CEST 2021
/app # top -n 1
Mem: 3902992K used, 4095752K free, 6520K shrd, 180504K buff, 1651716K cached
CPU: 14% usr 11% sys 0% nic 16% idle 52% io 0% irq 4% sirq
Load average: 5.06 3.25 2.38 3/984 1332
PID PPID USER STAT VSZ %VSZ CPU %CPU COMMAND
1 0 root S 692m 9% 0 0% /GetInfo
1157 0 root S 1720 0% 3 0% /bin/sh
1332 1157 root R 1652 0% 3 0% top -n 1
/app # exit
alfred@pc1:~$ kubectl top pod getinfo-6c84cff999-mtf5v --containers --use-protocol-buffers
POD NAME CPU(cores) MEMORY(bytes)
getinfo-6c84cff999-mtf5v getinfo 8m 5Mi
alfred@pc1:~$
Sieht ganz gut aus.