Читать книгу K8s Applications mit MicroK8S auf Raspberry PI - Alfred Sabitzer - Страница 13

Оглавление

Einfacher WebServer mit Go

Inspiration:

https://golang.org/doc/articles/wiki/

https://www.socketloop.com/tutorials/golang-get-hardware-information-such-as-disk-memory-and-cpu-usage

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.

K8s Applications mit MicroK8S auf Raspberry PI

Подняться наверх