added
This commit is contained in:
@@ -14,3 +14,12 @@ cdebug exec --privileged -it --image nixery.dev/shell/ps/vim/tshark my-distroles
|
|||||||
|
|
||||||
https://github.com/iximiuz/cdebug
|
https://github.com/iximiuz/cdebug
|
||||||
|
|
||||||
|
https://github.com/donaldzou/WGDashboard#-install
|
||||||
|
|
||||||
|
https://learnk8s.io/troubleshooting-deployments
|
||||||
|
|
||||||
|
https://artifacthub.io/
|
||||||
|
|
||||||
|
https://github.com/kubernetes/git-sync
|
||||||
|
|
||||||
|
https://grpc.io/docs/languages/python/basics/
|
||||||
14
git_sync/create_volume
Normal file
14
git_sync/create_volume
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolume
|
||||||
|
metadata:
|
||||||
|
name: pv-git
|
||||||
|
labels:
|
||||||
|
app: git
|
||||||
|
spec:
|
||||||
|
storageClassName: manual
|
||||||
|
capacity:
|
||||||
|
storage: 10Gi
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
hostPath:
|
||||||
|
path: "/mnt/data"
|
||||||
51
git_sync/deployment
Normal file
51
git_sync/deployment
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
creationTimestamp: null
|
||||||
|
labels:
|
||||||
|
app: git-sync
|
||||||
|
name: git-sync
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: git-sync
|
||||||
|
strategy: {}
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
creationTimestamp: null
|
||||||
|
labels:
|
||||||
|
app: git-sync
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- image: nginx:latest
|
||||||
|
name: nginx
|
||||||
|
resources: {}
|
||||||
|
volumeMounts:
|
||||||
|
- name: workdir
|
||||||
|
mountPath: /usr/share/nginx/html
|
||||||
|
initContainers:
|
||||||
|
- image: registry.k8s.io/git-sync/git-sync:v3.6.2
|
||||||
|
name: gitsync
|
||||||
|
args:
|
||||||
|
- --repo=nutzer26@1:/home/nutzer01/content_repo.git
|
||||||
|
- --root=/tmp/git/root
|
||||||
|
- --ssh
|
||||||
|
- --one-time
|
||||||
|
volumeMounts:
|
||||||
|
- name: git-secret
|
||||||
|
mountPath: /etc/git-secret
|
||||||
|
- name: workdir
|
||||||
|
mountPath: "/tmp/git/root"
|
||||||
|
securityContext:
|
||||||
|
runAsUser: 65533
|
||||||
|
volumes:
|
||||||
|
- name: workdir
|
||||||
|
emptyDir: {}
|
||||||
|
- name: claim-pvc2
|
||||||
|
secret:
|
||||||
|
secretName: git-creds
|
||||||
|
defaultMode: 0400
|
||||||
|
securityContext:
|
||||||
|
fsGroup: 65533
|
||||||
|
status: {}
|
||||||
1
git_sync/git_project/HEAD
Normal file
1
git_sync/git_project/HEAD
Normal file
@@ -0,0 +1 @@
|
|||||||
|
ref: refs/heads/master
|
||||||
4
git_sync/git_project/config
Normal file
4
git_sync/git_project/config
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
[core]
|
||||||
|
repositoryformatversion = 0
|
||||||
|
filemode = true
|
||||||
|
bare = true
|
||||||
1
git_sync/git_project/description
Normal file
1
git_sync/git_project/description
Normal file
@@ -0,0 +1 @@
|
|||||||
|
Unnamed repository; edit this file 'description' to name the repository.
|
||||||
15
git_sync/git_project/hooks/applypatch-msg.sample
Executable file
15
git_sync/git_project/hooks/applypatch-msg.sample
Executable file
@@ -0,0 +1,15 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# An example hook script to check the commit log message taken by
|
||||||
|
# applypatch from an e-mail message.
|
||||||
|
#
|
||||||
|
# The hook should exit with non-zero status after issuing an
|
||||||
|
# appropriate message if it wants to stop the commit. The hook is
|
||||||
|
# allowed to edit the commit message file.
|
||||||
|
#
|
||||||
|
# To enable this hook, rename this file to "applypatch-msg".
|
||||||
|
|
||||||
|
. git-sh-setup
|
||||||
|
commitmsg="$(git rev-parse --git-path hooks/commit-msg)"
|
||||||
|
test -x "$commitmsg" && exec "$commitmsg" ${1+"$@"}
|
||||||
|
:
|
||||||
24
git_sync/git_project/hooks/commit-msg.sample
Executable file
24
git_sync/git_project/hooks/commit-msg.sample
Executable file
@@ -0,0 +1,24 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# An example hook script to check the commit log message.
|
||||||
|
# Called by "git commit" with one argument, the name of the file
|
||||||
|
# that has the commit message. The hook should exit with non-zero
|
||||||
|
# status after issuing an appropriate message if it wants to stop the
|
||||||
|
# commit. The hook is allowed to edit the commit message file.
|
||||||
|
#
|
||||||
|
# To enable this hook, rename this file to "commit-msg".
|
||||||
|
|
||||||
|
# Uncomment the below to add a Signed-off-by line to the message.
|
||||||
|
# Doing this in a hook is a bad idea in general, but the prepare-commit-msg
|
||||||
|
# hook is more suited to it.
|
||||||
|
#
|
||||||
|
# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
|
||||||
|
# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"
|
||||||
|
|
||||||
|
# This example catches duplicate Signed-off-by lines.
|
||||||
|
|
||||||
|
test "" = "$(grep '^Signed-off-by: ' "$1" |
|
||||||
|
sort | uniq -c | sed -e '/^[ ]*1[ ]/d')" || {
|
||||||
|
echo >&2 Duplicate Signed-off-by lines.
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
109
git_sync/git_project/hooks/fsmonitor-watchman.sample
Executable file
109
git_sync/git_project/hooks/fsmonitor-watchman.sample
Executable file
@@ -0,0 +1,109 @@
|
|||||||
|
#!/usr/bin/perl
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
use IPC::Open2;
|
||||||
|
|
||||||
|
# An example hook script to integrate Watchman
|
||||||
|
# (https://facebook.github.io/watchman/) with git to speed up detecting
|
||||||
|
# new and modified files.
|
||||||
|
#
|
||||||
|
# The hook is passed a version (currently 1) and a time in nanoseconds
|
||||||
|
# formatted as a string and outputs to stdout all files that have been
|
||||||
|
# modified since the given time. Paths must be relative to the root of
|
||||||
|
# the working tree and separated by a single NUL.
|
||||||
|
#
|
||||||
|
# To enable this hook, rename this file to "query-watchman" and set
|
||||||
|
# 'git config core.fsmonitor .git/hooks/query-watchman'
|
||||||
|
#
|
||||||
|
my ($version, $time) = @ARGV;
|
||||||
|
|
||||||
|
# Check the hook interface version
|
||||||
|
|
||||||
|
if ($version == 1) {
|
||||||
|
# convert nanoseconds to seconds
|
||||||
|
# subtract one second to make sure watchman will return all changes
|
||||||
|
$time = int ($time / 1000000000) - 1;
|
||||||
|
} else {
|
||||||
|
die "Unsupported query-fsmonitor hook version '$version'.\n" .
|
||||||
|
"Falling back to scanning...\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
my $git_work_tree;
|
||||||
|
if ($^O =~ 'msys' || $^O =~ 'cygwin') {
|
||||||
|
$git_work_tree = Win32::GetCwd();
|
||||||
|
$git_work_tree =~ tr/\\/\//;
|
||||||
|
} else {
|
||||||
|
require Cwd;
|
||||||
|
$git_work_tree = Cwd::cwd();
|
||||||
|
}
|
||||||
|
|
||||||
|
my $retry = 1;
|
||||||
|
|
||||||
|
launch_watchman();
|
||||||
|
|
||||||
|
sub launch_watchman {
|
||||||
|
|
||||||
|
my $pid = open2(\*CHLD_OUT, \*CHLD_IN, 'watchman -j --no-pretty')
|
||||||
|
or die "open2() failed: $!\n" .
|
||||||
|
"Falling back to scanning...\n";
|
||||||
|
|
||||||
|
# In the query expression below we're asking for names of files that
|
||||||
|
# changed since $time but were not transient (ie created after
|
||||||
|
# $time but no longer exist).
|
||||||
|
#
|
||||||
|
# To accomplish this, we're using the "since" generator to use the
|
||||||
|
# recency index to select candidate nodes and "fields" to limit the
|
||||||
|
# output to file names only.
|
||||||
|
|
||||||
|
my $query = <<" END";
|
||||||
|
["query", "$git_work_tree", {
|
||||||
|
"since": $time,
|
||||||
|
"fields": ["name"]
|
||||||
|
}]
|
||||||
|
END
|
||||||
|
|
||||||
|
print CHLD_IN $query;
|
||||||
|
close CHLD_IN;
|
||||||
|
my $response = do {local $/; <CHLD_OUT>};
|
||||||
|
|
||||||
|
die "Watchman: command returned no output.\n" .
|
||||||
|
"Falling back to scanning...\n" if $response eq "";
|
||||||
|
die "Watchman: command returned invalid output: $response\n" .
|
||||||
|
"Falling back to scanning...\n" unless $response =~ /^\{/;
|
||||||
|
|
||||||
|
my $json_pkg;
|
||||||
|
eval {
|
||||||
|
require JSON::XS;
|
||||||
|
$json_pkg = "JSON::XS";
|
||||||
|
1;
|
||||||
|
} or do {
|
||||||
|
require JSON::PP;
|
||||||
|
$json_pkg = "JSON::PP";
|
||||||
|
};
|
||||||
|
|
||||||
|
my $o = $json_pkg->new->utf8->decode($response);
|
||||||
|
|
||||||
|
if ($retry > 0 and $o->{error} and $o->{error} =~ m/unable to resolve root .* directory (.*) is not watched/) {
|
||||||
|
print STDERR "Adding '$git_work_tree' to watchman's watch list.\n";
|
||||||
|
$retry--;
|
||||||
|
qx/watchman watch "$git_work_tree"/;
|
||||||
|
die "Failed to make watchman watch '$git_work_tree'.\n" .
|
||||||
|
"Falling back to scanning...\n" if $? != 0;
|
||||||
|
|
||||||
|
# Watchman will always return all files on the first query so
|
||||||
|
# return the fast "everything is dirty" flag to git and do the
|
||||||
|
# Watchman query just to get it over with now so we won't pay
|
||||||
|
# the cost in git to look up each individual file.
|
||||||
|
print "/\0";
|
||||||
|
eval { launch_watchman() };
|
||||||
|
exit 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
die "Watchman: $o->{error}.\n" .
|
||||||
|
"Falling back to scanning...\n" if $o->{error};
|
||||||
|
|
||||||
|
binmode STDOUT, ":utf8";
|
||||||
|
local $, = "\0";
|
||||||
|
print @{$o->{files}};
|
||||||
|
}
|
||||||
8
git_sync/git_project/hooks/post-update.sample
Executable file
8
git_sync/git_project/hooks/post-update.sample
Executable file
@@ -0,0 +1,8 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# An example hook script to prepare a packed repository for use over
|
||||||
|
# dumb transports.
|
||||||
|
#
|
||||||
|
# To enable this hook, rename this file to "post-update".
|
||||||
|
|
||||||
|
exec git update-server-info
|
||||||
14
git_sync/git_project/hooks/pre-applypatch.sample
Executable file
14
git_sync/git_project/hooks/pre-applypatch.sample
Executable file
@@ -0,0 +1,14 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# An example hook script to verify what is about to be committed
|
||||||
|
# by applypatch from an e-mail message.
|
||||||
|
#
|
||||||
|
# The hook should exit with non-zero status after issuing an
|
||||||
|
# appropriate message if it wants to stop the commit.
|
||||||
|
#
|
||||||
|
# To enable this hook, rename this file to "pre-applypatch".
|
||||||
|
|
||||||
|
. git-sh-setup
|
||||||
|
precommit="$(git rev-parse --git-path hooks/pre-commit)"
|
||||||
|
test -x "$precommit" && exec "$precommit" ${1+"$@"}
|
||||||
|
:
|
||||||
49
git_sync/git_project/hooks/pre-commit.sample
Executable file
49
git_sync/git_project/hooks/pre-commit.sample
Executable file
@@ -0,0 +1,49 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# An example hook script to verify what is about to be committed.
|
||||||
|
# Called by "git commit" with no arguments. The hook should
|
||||||
|
# exit with non-zero status after issuing an appropriate message if
|
||||||
|
# it wants to stop the commit.
|
||||||
|
#
|
||||||
|
# To enable this hook, rename this file to "pre-commit".
|
||||||
|
|
||||||
|
if git rev-parse --verify HEAD >/dev/null 2>&1
|
||||||
|
then
|
||||||
|
against=HEAD
|
||||||
|
else
|
||||||
|
# Initial commit: diff against an empty tree object
|
||||||
|
against=$(git hash-object -t tree /dev/null)
|
||||||
|
fi
|
||||||
|
|
||||||
|
# If you want to allow non-ASCII filenames set this variable to true.
|
||||||
|
allownonascii=$(git config --bool hooks.allownonascii)
|
||||||
|
|
||||||
|
# Redirect output to stderr.
|
||||||
|
exec 1>&2
|
||||||
|
|
||||||
|
# Cross platform projects tend to avoid non-ASCII filenames; prevent
|
||||||
|
# them from being added to the repository. We exploit the fact that the
|
||||||
|
# printable range starts at the space character and ends with tilde.
|
||||||
|
if [ "$allownonascii" != "true" ] &&
|
||||||
|
# Note that the use of brackets around a tr range is ok here, (it's
|
||||||
|
# even required, for portability to Solaris 10's /usr/bin/tr), since
|
||||||
|
# the square bracket bytes happen to fall in the designated range.
|
||||||
|
test $(git diff --cached --name-only --diff-filter=A -z $against |
|
||||||
|
LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0
|
||||||
|
then
|
||||||
|
cat <<\EOF
|
||||||
|
Error: Attempt to add a non-ASCII file name.
|
||||||
|
|
||||||
|
This can cause problems if you want to work with people on other platforms.
|
||||||
|
|
||||||
|
To be portable it is advisable to rename the file.
|
||||||
|
|
||||||
|
If you know what you are doing you can disable this check using:
|
||||||
|
|
||||||
|
git config hooks.allownonascii true
|
||||||
|
EOF
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# If there are whitespace errors, print the offending file names and fail.
|
||||||
|
exec git diff-index --check --cached $against --
|
||||||
13
git_sync/git_project/hooks/pre-merge-commit.sample
Executable file
13
git_sync/git_project/hooks/pre-merge-commit.sample
Executable file
@@ -0,0 +1,13 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# An example hook script to verify what is about to be committed.
|
||||||
|
# Called by "git merge" with no arguments. The hook should
|
||||||
|
# exit with non-zero status after issuing an appropriate message to
|
||||||
|
# stderr if it wants to stop the merge commit.
|
||||||
|
#
|
||||||
|
# To enable this hook, rename this file to "pre-merge-commit".
|
||||||
|
|
||||||
|
. git-sh-setup
|
||||||
|
test -x "$GIT_DIR/hooks/pre-commit" &&
|
||||||
|
exec "$GIT_DIR/hooks/pre-commit"
|
||||||
|
:
|
||||||
53
git_sync/git_project/hooks/pre-push.sample
Executable file
53
git_sync/git_project/hooks/pre-push.sample
Executable file
@@ -0,0 +1,53 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# An example hook script to verify what is about to be pushed. Called by "git
|
||||||
|
# push" after it has checked the remote status, but before anything has been
|
||||||
|
# pushed. If this script exits with a non-zero status nothing will be pushed.
|
||||||
|
#
|
||||||
|
# This hook is called with the following parameters:
|
||||||
|
#
|
||||||
|
# $1 -- Name of the remote to which the push is being done
|
||||||
|
# $2 -- URL to which the push is being done
|
||||||
|
#
|
||||||
|
# If pushing without using a named remote those arguments will be equal.
|
||||||
|
#
|
||||||
|
# Information about the commits which are being pushed is supplied as lines to
|
||||||
|
# the standard input in the form:
|
||||||
|
#
|
||||||
|
# <local ref> <local sha1> <remote ref> <remote sha1>
|
||||||
|
#
|
||||||
|
# This sample shows how to prevent push of commits where the log message starts
|
||||||
|
# with "WIP" (work in progress).
|
||||||
|
|
||||||
|
remote="$1"
|
||||||
|
url="$2"
|
||||||
|
|
||||||
|
z40=0000000000000000000000000000000000000000
|
||||||
|
|
||||||
|
while read local_ref local_sha remote_ref remote_sha
|
||||||
|
do
|
||||||
|
if [ "$local_sha" = $z40 ]
|
||||||
|
then
|
||||||
|
# Handle delete
|
||||||
|
:
|
||||||
|
else
|
||||||
|
if [ "$remote_sha" = $z40 ]
|
||||||
|
then
|
||||||
|
# New branch, examine all commits
|
||||||
|
range="$local_sha"
|
||||||
|
else
|
||||||
|
# Update to existing branch, examine new commits
|
||||||
|
range="$remote_sha..$local_sha"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check for WIP commit
|
||||||
|
commit=`git rev-list -n 1 --grep '^WIP' "$range"`
|
||||||
|
if [ -n "$commit" ]
|
||||||
|
then
|
||||||
|
echo >&2 "Found WIP commit in $local_ref, not pushing"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
exit 0
|
||||||
169
git_sync/git_project/hooks/pre-rebase.sample
Executable file
169
git_sync/git_project/hooks/pre-rebase.sample
Executable file
@@ -0,0 +1,169 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# Copyright (c) 2006, 2008 Junio C Hamano
|
||||||
|
#
|
||||||
|
# The "pre-rebase" hook is run just before "git rebase" starts doing
|
||||||
|
# its job, and can prevent the command from running by exiting with
|
||||||
|
# non-zero status.
|
||||||
|
#
|
||||||
|
# The hook is called with the following parameters:
|
||||||
|
#
|
||||||
|
# $1 -- the upstream the series was forked from.
|
||||||
|
# $2 -- the branch being rebased (or empty when rebasing the current branch).
|
||||||
|
#
|
||||||
|
# This sample shows how to prevent topic branches that are already
|
||||||
|
# merged to 'next' branch from getting rebased, because allowing it
|
||||||
|
# would result in rebasing already published history.
|
||||||
|
|
||||||
|
publish=next
|
||||||
|
basebranch="$1"
|
||||||
|
if test "$#" = 2
|
||||||
|
then
|
||||||
|
topic="refs/heads/$2"
|
||||||
|
else
|
||||||
|
topic=`git symbolic-ref HEAD` ||
|
||||||
|
exit 0 ;# we do not interrupt rebasing detached HEAD
|
||||||
|
fi
|
||||||
|
|
||||||
|
case "$topic" in
|
||||||
|
refs/heads/??/*)
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
exit 0 ;# we do not interrupt others.
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Now we are dealing with a topic branch being rebased
|
||||||
|
# on top of master. Is it OK to rebase it?
|
||||||
|
|
||||||
|
# Does the topic really exist?
|
||||||
|
git show-ref -q "$topic" || {
|
||||||
|
echo >&2 "No such branch $topic"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Is topic fully merged to master?
|
||||||
|
not_in_master=`git rev-list --pretty=oneline ^master "$topic"`
|
||||||
|
if test -z "$not_in_master"
|
||||||
|
then
|
||||||
|
echo >&2 "$topic is fully merged to master; better remove it."
|
||||||
|
exit 1 ;# we could allow it, but there is no point.
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Is topic ever merged to next? If so you should not be rebasing it.
|
||||||
|
only_next_1=`git rev-list ^master "^$topic" ${publish} | sort`
|
||||||
|
only_next_2=`git rev-list ^master ${publish} | sort`
|
||||||
|
if test "$only_next_1" = "$only_next_2"
|
||||||
|
then
|
||||||
|
not_in_topic=`git rev-list "^$topic" master`
|
||||||
|
if test -z "$not_in_topic"
|
||||||
|
then
|
||||||
|
echo >&2 "$topic is already up to date with master"
|
||||||
|
exit 1 ;# we could allow it, but there is no point.
|
||||||
|
else
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
not_in_next=`git rev-list --pretty=oneline ^${publish} "$topic"`
|
||||||
|
/usr/bin/perl -e '
|
||||||
|
my $topic = $ARGV[0];
|
||||||
|
my $msg = "* $topic has commits already merged to public branch:\n";
|
||||||
|
my (%not_in_next) = map {
|
||||||
|
/^([0-9a-f]+) /;
|
||||||
|
($1 => 1);
|
||||||
|
} split(/\n/, $ARGV[1]);
|
||||||
|
for my $elem (map {
|
||||||
|
/^([0-9a-f]+) (.*)$/;
|
||||||
|
[$1 => $2];
|
||||||
|
} split(/\n/, $ARGV[2])) {
|
||||||
|
if (!exists $not_in_next{$elem->[0]}) {
|
||||||
|
if ($msg) {
|
||||||
|
print STDERR $msg;
|
||||||
|
undef $msg;
|
||||||
|
}
|
||||||
|
print STDERR " $elem->[1]\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
' "$topic" "$not_in_next" "$not_in_master"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
<<\DOC_END
|
||||||
|
|
||||||
|
This sample hook safeguards topic branches that have been
|
||||||
|
published from being rewound.
|
||||||
|
|
||||||
|
The workflow assumed here is:
|
||||||
|
|
||||||
|
* Once a topic branch forks from "master", "master" is never
|
||||||
|
merged into it again (either directly or indirectly).
|
||||||
|
|
||||||
|
* Once a topic branch is fully cooked and merged into "master",
|
||||||
|
it is deleted. If you need to build on top of it to correct
|
||||||
|
earlier mistakes, a new topic branch is created by forking at
|
||||||
|
the tip of the "master". This is not strictly necessary, but
|
||||||
|
it makes it easier to keep your history simple.
|
||||||
|
|
||||||
|
* Whenever you need to test or publish your changes to topic
|
||||||
|
branches, merge them into "next" branch.
|
||||||
|
|
||||||
|
The script, being an example, hardcodes the publish branch name
|
||||||
|
to be "next", but it is trivial to make it configurable via
|
||||||
|
$GIT_DIR/config mechanism.
|
||||||
|
|
||||||
|
With this workflow, you would want to know:
|
||||||
|
|
||||||
|
(1) ... if a topic branch has ever been merged to "next". Young
|
||||||
|
topic branches can have stupid mistakes you would rather
|
||||||
|
clean up before publishing, and things that have not been
|
||||||
|
merged into other branches can be easily rebased without
|
||||||
|
affecting other people. But once it is published, you would
|
||||||
|
not want to rewind it.
|
||||||
|
|
||||||
|
(2) ... if a topic branch has been fully merged to "master".
|
||||||
|
Then you can delete it. More importantly, you should not
|
||||||
|
build on top of it -- other people may already want to
|
||||||
|
change things related to the topic as patches against your
|
||||||
|
"master", so if you need further changes, it is better to
|
||||||
|
fork the topic (perhaps with the same name) afresh from the
|
||||||
|
tip of "master".
|
||||||
|
|
||||||
|
Let's look at this example:
|
||||||
|
|
||||||
|
o---o---o---o---o---o---o---o---o---o "next"
|
||||||
|
/ / / /
|
||||||
|
/ a---a---b A / /
|
||||||
|
/ / / /
|
||||||
|
/ / c---c---c---c B /
|
||||||
|
/ / / \ /
|
||||||
|
/ / / b---b C \ /
|
||||||
|
/ / / / \ /
|
||||||
|
---o---o---o---o---o---o---o---o---o---o---o "master"
|
||||||
|
|
||||||
|
|
||||||
|
A, B and C are topic branches.
|
||||||
|
|
||||||
|
* A has one fix since it was merged up to "next".
|
||||||
|
|
||||||
|
* B has finished. It has been fully merged up to "master" and "next",
|
||||||
|
and is ready to be deleted.
|
||||||
|
|
||||||
|
* C has not merged to "next" at all.
|
||||||
|
|
||||||
|
We would want to allow C to be rebased, refuse A, and encourage
|
||||||
|
B to be deleted.
|
||||||
|
|
||||||
|
To compute (1):
|
||||||
|
|
||||||
|
git rev-list ^master ^topic next
|
||||||
|
git rev-list ^master next
|
||||||
|
|
||||||
|
if these match, topic has not merged in next at all.
|
||||||
|
|
||||||
|
To compute (2):
|
||||||
|
|
||||||
|
git rev-list master..topic
|
||||||
|
|
||||||
|
if this is empty, it is fully merged to "master".
|
||||||
|
|
||||||
|
DOC_END
|
||||||
24
git_sync/git_project/hooks/pre-receive.sample
Executable file
24
git_sync/git_project/hooks/pre-receive.sample
Executable file
@@ -0,0 +1,24 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# An example hook script to make use of push options.
|
||||||
|
# The example simply echoes all push options that start with 'echoback='
|
||||||
|
# and rejects all pushes when the "reject" push option is used.
|
||||||
|
#
|
||||||
|
# To enable this hook, rename this file to "pre-receive".
|
||||||
|
|
||||||
|
if test -n "$GIT_PUSH_OPTION_COUNT"
|
||||||
|
then
|
||||||
|
i=0
|
||||||
|
while test "$i" -lt "$GIT_PUSH_OPTION_COUNT"
|
||||||
|
do
|
||||||
|
eval "value=\$GIT_PUSH_OPTION_$i"
|
||||||
|
case "$value" in
|
||||||
|
echoback=*)
|
||||||
|
echo "echo from the pre-receive-hook: ${value#*=}" >&2
|
||||||
|
;;
|
||||||
|
reject)
|
||||||
|
exit 1
|
||||||
|
esac
|
||||||
|
i=$((i + 1))
|
||||||
|
done
|
||||||
|
fi
|
||||||
42
git_sync/git_project/hooks/prepare-commit-msg.sample
Executable file
42
git_sync/git_project/hooks/prepare-commit-msg.sample
Executable file
@@ -0,0 +1,42 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# An example hook script to prepare the commit log message.
|
||||||
|
# Called by "git commit" with the name of the file that has the
|
||||||
|
# commit message, followed by the description of the commit
|
||||||
|
# message's source. The hook's purpose is to edit the commit
|
||||||
|
# message file. If the hook fails with a non-zero status,
|
||||||
|
# the commit is aborted.
|
||||||
|
#
|
||||||
|
# To enable this hook, rename this file to "prepare-commit-msg".
|
||||||
|
|
||||||
|
# This hook includes three examples. The first one removes the
|
||||||
|
# "# Please enter the commit message..." help message.
|
||||||
|
#
|
||||||
|
# The second includes the output of "git diff --name-status -r"
|
||||||
|
# into the message, just before the "git status" output. It is
|
||||||
|
# commented because it doesn't cope with --amend or with squashed
|
||||||
|
# commits.
|
||||||
|
#
|
||||||
|
# The third example adds a Signed-off-by line to the message, that can
|
||||||
|
# still be edited. This is rarely a good idea.
|
||||||
|
|
||||||
|
COMMIT_MSG_FILE=$1
|
||||||
|
COMMIT_SOURCE=$2
|
||||||
|
SHA1=$3
|
||||||
|
|
||||||
|
/usr/bin/perl -i.bak -ne 'print unless(m/^. Please enter the commit message/..m/^#$/)' "$COMMIT_MSG_FILE"
|
||||||
|
|
||||||
|
# case "$COMMIT_SOURCE,$SHA1" in
|
||||||
|
# ,|template,)
|
||||||
|
# /usr/bin/perl -i.bak -pe '
|
||||||
|
# print "\n" . `git diff --cached --name-status -r`
|
||||||
|
# if /^#/ && $first++ == 0' "$COMMIT_MSG_FILE" ;;
|
||||||
|
# *) ;;
|
||||||
|
# esac
|
||||||
|
|
||||||
|
# SOB=$(git var GIT_COMMITTER_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
|
||||||
|
# git interpret-trailers --in-place --trailer "$SOB" "$COMMIT_MSG_FILE"
|
||||||
|
# if test -z "$COMMIT_SOURCE"
|
||||||
|
# then
|
||||||
|
# /usr/bin/perl -i.bak -pe 'print "\n" if !$first_line++' "$COMMIT_MSG_FILE"
|
||||||
|
# fi
|
||||||
128
git_sync/git_project/hooks/update.sample
Executable file
128
git_sync/git_project/hooks/update.sample
Executable file
@@ -0,0 +1,128 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# An example hook script to block unannotated tags from entering.
|
||||||
|
# Called by "git receive-pack" with arguments: refname sha1-old sha1-new
|
||||||
|
#
|
||||||
|
# To enable this hook, rename this file to "update".
|
||||||
|
#
|
||||||
|
# Config
|
||||||
|
# ------
|
||||||
|
# hooks.allowunannotated
|
||||||
|
# This boolean sets whether unannotated tags will be allowed into the
|
||||||
|
# repository. By default they won't be.
|
||||||
|
# hooks.allowdeletetag
|
||||||
|
# This boolean sets whether deleting tags will be allowed in the
|
||||||
|
# repository. By default they won't be.
|
||||||
|
# hooks.allowmodifytag
|
||||||
|
# This boolean sets whether a tag may be modified after creation. By default
|
||||||
|
# it won't be.
|
||||||
|
# hooks.allowdeletebranch
|
||||||
|
# This boolean sets whether deleting branches will be allowed in the
|
||||||
|
# repository. By default they won't be.
|
||||||
|
# hooks.denycreatebranch
|
||||||
|
# This boolean sets whether remotely creating branches will be denied
|
||||||
|
# in the repository. By default this is allowed.
|
||||||
|
#
|
||||||
|
|
||||||
|
# --- Command line
|
||||||
|
refname="$1"
|
||||||
|
oldrev="$2"
|
||||||
|
newrev="$3"
|
||||||
|
|
||||||
|
# --- Safety check
|
||||||
|
if [ -z "$GIT_DIR" ]; then
|
||||||
|
echo "Don't run this script from the command line." >&2
|
||||||
|
echo " (if you want, you could supply GIT_DIR then run" >&2
|
||||||
|
echo " $0 <ref> <oldrev> <newrev>)" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then
|
||||||
|
echo "usage: $0 <ref> <oldrev> <newrev>" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# --- Config
|
||||||
|
allowunannotated=$(git config --bool hooks.allowunannotated)
|
||||||
|
allowdeletebranch=$(git config --bool hooks.allowdeletebranch)
|
||||||
|
denycreatebranch=$(git config --bool hooks.denycreatebranch)
|
||||||
|
allowdeletetag=$(git config --bool hooks.allowdeletetag)
|
||||||
|
allowmodifytag=$(git config --bool hooks.allowmodifytag)
|
||||||
|
|
||||||
|
# check for no description
|
||||||
|
projectdesc=$(sed -e '1q' "$GIT_DIR/description")
|
||||||
|
case "$projectdesc" in
|
||||||
|
"Unnamed repository"* | "")
|
||||||
|
echo "*** Project description file hasn't been set" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# --- Check types
|
||||||
|
# if $newrev is 0000...0000, it's a commit to delete a ref.
|
||||||
|
zero="0000000000000000000000000000000000000000"
|
||||||
|
if [ "$newrev" = "$zero" ]; then
|
||||||
|
newrev_type=delete
|
||||||
|
else
|
||||||
|
newrev_type=$(git cat-file -t $newrev)
|
||||||
|
fi
|
||||||
|
|
||||||
|
case "$refname","$newrev_type" in
|
||||||
|
refs/tags/*,commit)
|
||||||
|
# un-annotated tag
|
||||||
|
short_refname=${refname##refs/tags/}
|
||||||
|
if [ "$allowunannotated" != "true" ]; then
|
||||||
|
echo "*** The un-annotated tag, $short_refname, is not allowed in this repository" >&2
|
||||||
|
echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
refs/tags/*,delete)
|
||||||
|
# delete tag
|
||||||
|
if [ "$allowdeletetag" != "true" ]; then
|
||||||
|
echo "*** Deleting a tag is not allowed in this repository" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
refs/tags/*,tag)
|
||||||
|
# annotated tag
|
||||||
|
if [ "$allowmodifytag" != "true" ] && git rev-parse $refname > /dev/null 2>&1
|
||||||
|
then
|
||||||
|
echo "*** Tag '$refname' already exists." >&2
|
||||||
|
echo "*** Modifying a tag is not allowed in this repository." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
refs/heads/*,commit)
|
||||||
|
# branch
|
||||||
|
if [ "$oldrev" = "$zero" -a "$denycreatebranch" = "true" ]; then
|
||||||
|
echo "*** Creating a branch is not allowed in this repository" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
refs/heads/*,delete)
|
||||||
|
# delete branch
|
||||||
|
if [ "$allowdeletebranch" != "true" ]; then
|
||||||
|
echo "*** Deleting a branch is not allowed in this repository" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
refs/remotes/*,commit)
|
||||||
|
# tracking branch
|
||||||
|
;;
|
||||||
|
refs/remotes/*,delete)
|
||||||
|
# delete tracking branch
|
||||||
|
if [ "$allowdeletebranch" != "true" ]; then
|
||||||
|
echo "*** Deleting a tracking branch is not allowed in this repository" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
# Anything else (is there anything else?)
|
||||||
|
echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# --- Finished
|
||||||
|
exit 0
|
||||||
6
git_sync/git_project/info/exclude
Normal file
6
git_sync/git_project/info/exclude
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
# git ls-files --others --exclude-from=.git/info/exclude
|
||||||
|
# Lines that start with '#' are comments.
|
||||||
|
# For a project mostly in C, the following would be a good set of
|
||||||
|
# exclude patterns (uncomment them if you want to use them):
|
||||||
|
# *.[oa]
|
||||||
|
# *~
|
||||||
13
git_sync/pvc
Normal file
13
git_sync/pvc
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: pvc-claim-2
|
||||||
|
labels:
|
||||||
|
app: git
|
||||||
|
spec:
|
||||||
|
storageClassName: manual
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 3Gi
|
||||||
128
k3d/blue-green/doku
Normal file
128
k3d/blue-green/doku
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
Blue Green Deployment
|
||||||
|
|
||||||
|
create version 1 and 2 and services
|
||||||
|
|
||||||
|
# prepare namespace
|
||||||
|
|
||||||
|
|
||||||
|
mkdir ~/blue-green && cd ~/blue-green
|
||||||
|
kubectl create namespace blue-green
|
||||||
|
kubectl config set-context --current --namespace blue-green
|
||||||
|
|
||||||
|
# create manifests
|
||||||
|
|
||||||
|
cat >nginx-v1.yaml <<EOF
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: web
|
||||||
|
version: V1.0.0
|
||||||
|
name: webv1
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: web
|
||||||
|
version: V1.0.0
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: web
|
||||||
|
version: V1.0.0
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- image: nginx:1.19.3
|
||||||
|
name: nginx
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
containerPort: 80
|
||||||
|
EOF
|
||||||
|
|
||||||
|
cat >nginx-v2.yaml <<EOF
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: web
|
||||||
|
version: V2.0.0
|
||||||
|
name: webv2
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: web
|
||||||
|
version: V2.0.0
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: web
|
||||||
|
version: V2.0.0
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- image: nginx:1.19.8
|
||||||
|
name: nginx
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
containerPort: 80
|
||||||
|
EOF
|
||||||
|
cat >nginx-svc.yaml <<EOF
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: web
|
||||||
|
name: nginx
|
||||||
|
spec:
|
||||||
|
ports:
|
||||||
|
- port: 80
|
||||||
|
protocol: TCP
|
||||||
|
targetPort: 80
|
||||||
|
selector:
|
||||||
|
app: web
|
||||||
|
version: V1.0.0
|
||||||
|
EOF
|
||||||
|
|
||||||
|
Deployment from blue to green
|
||||||
|
|
||||||
|
|
||||||
|
# deploy blue
|
||||||
|
|
||||||
|
kubectl apply -f nginx-v1.yaml
|
||||||
|
kubectl apply -f nginx-svc.yaml
|
||||||
|
kubectl describe deployment webv1
|
||||||
|
kubectl describe svc nginx
|
||||||
|
kubectl get ep nginx
|
||||||
|
|
||||||
|
# deploy green
|
||||||
|
kubectl apply -f nginx-v2.yaml
|
||||||
|
|
||||||
|
# traffic shift
|
||||||
|
kubectl patch service nginx --patch '{"spec":{"selector":{"version":"V2.0.0"}}}'
|
||||||
|
|
||||||
|
# Test if the second deployment was successful
|
||||||
|
kubectl describe deployment webv2
|
||||||
|
kubectl describe svc nginx
|
||||||
|
kubectl get ep nginx
|
||||||
|
|
||||||
|
# cleanup v1
|
||||||
|
|
||||||
|
kubectl delete deploy webv1
|
||||||
|
|
||||||
|
WARNING:Traefik shift don't change established connection!!
|
||||||
|
|
||||||
|
kubectl run nc -it --rm --image curlimages/curl -- /bin/sh
|
||||||
|
nc nginx.blue-green.svc.cluster.local 80
|
||||||
|
GET /index.html HTTP/1.1
|
||||||
|
Host: localhost
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
# switch at other terminal the load with patch
|
||||||
|
#kubectl patch service nginx --patch '{"spec":{"selector":{"version":"V1.0.0"}}}'
|
||||||
|
|
||||||
|
GET /index.html HTTP/1.1
|
||||||
|
Host: localhost
|
||||||
|
|
||||||
|
# same server/pod answer ...
|
||||||
|
|
||||||
14
k3d/blue-green/nginx-svc.yaml
Normal file
14
k3d/blue-green/nginx-svc.yaml
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: web
|
||||||
|
name: nginx
|
||||||
|
spec:
|
||||||
|
ports:
|
||||||
|
- port: 80
|
||||||
|
protocol: TCP
|
||||||
|
targetPort: 80
|
||||||
|
selector:
|
||||||
|
app: web
|
||||||
|
version: V1.0.0
|
||||||
25
k3d/blue-green/nginx-v1.yaml
Normal file
25
k3d/blue-green/nginx-v1.yaml
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: web
|
||||||
|
version: V1.0.0
|
||||||
|
name: webv1
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: web
|
||||||
|
version: V1.0.0
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: web
|
||||||
|
version: V1.0.0
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- image: nginx:1.19.3
|
||||||
|
name: nginx_new
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
containerPort: 80
|
||||||
25
k3d/blue-green/nginx-v2.yaml
Normal file
25
k3d/blue-green/nginx-v2.yaml
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: web
|
||||||
|
version: V2.0.0
|
||||||
|
name: webv2
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: web
|
||||||
|
version: V2.0.0
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: web
|
||||||
|
version: V2.0.0
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- image: nginx:1.19.8
|
||||||
|
name: nginx_old
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
containerPort: 80
|
||||||
@@ -73,4 +73,16 @@ echo "deb https://apt.kubernetes.io/ kubernetes-xenial main" \
|
|||||||
|
|
||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
sudo apt-get install -y kubectl
|
sudo apt-get install -y kubectl
|
||||||
|
|
||||||
source <(kubectl completion bash)
|
source <(kubectl completion bash)
|
||||||
|
source <(k3d completion bash)
|
||||||
|
|
||||||
|
curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3
|
||||||
|
chmod 700 get_helm.sh
|
||||||
|
./get_helm.sh
|
||||||
|
source <(helm completion bash)
|
||||||
|
|
||||||
|
|
||||||
|
default Namespace nächste commands
|
||||||
|
|
||||||
|
kubectl config set-context --current --namespace whoami
|
||||||
201
k3d/pod_init/doku
Normal file
201
k3d/pod_init/doku
Normal file
@@ -0,0 +1,201 @@
|
|||||||
|
Pod init container
|
||||||
|
|
||||||
|
https://kubernetes.io/docs/concepts/workloads/pods/init-containers/
|
||||||
|
|
||||||
|
A Pod can have multiple containers running apps within it, but it can also have one or more init containers, which are run before the app containers are started.
|
||||||
|
|
||||||
|
Init containers are exactly like regular containers, except:
|
||||||
|
|
||||||
|
Init containers always run to completion.
|
||||||
|
Each init container must complete successfully before the next one starts.
|
||||||
|
|
||||||
|
If a Pod's init container fails, the kubelet repeatedly restarts that init container until it succeeds. However, if the Pod has a restartPolicy of Never, and an init container fails during startup of that Pod, Kubernetes treats the overall Pod as failed.
|
||||||
|
|
||||||
|
kubectl delete service whoami
|
||||||
|
cat >myapp-pod.yaml <<EOF
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Pod
|
||||||
|
metadata:
|
||||||
|
name: myapp-pod
|
||||||
|
labels:
|
||||||
|
app: myapp
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: myapp-container
|
||||||
|
image: busybox:1.28
|
||||||
|
command: ['sh', '-c', 'echo The app is running! && sleep 30']
|
||||||
|
initContainers:
|
||||||
|
- name: init-whoami
|
||||||
|
image: busybox:1.28
|
||||||
|
command: ['sh', '-c', "until nslookup whoami.\$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for whoami; sleep 2; done"]
|
||||||
|
EOF
|
||||||
|
kubectl apply -f myapp-pod.yaml
|
||||||
|
kubectl describe pod myapp-pod
|
||||||
|
# initContainer not ready
|
||||||
|
kubectl apply -f service.yaml
|
||||||
|
kubectl describe pod myapp-pod
|
||||||
|
|
||||||
|
https://github.com/groundnuty/k8s-wait-for
|
||||||
|
|
||||||
|
cat >myapp-pod-exists.yaml <<EOF
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Pod
|
||||||
|
metadata:
|
||||||
|
name: myapp-pod-exists
|
||||||
|
labels:
|
||||||
|
app: myapp
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: myapp-container
|
||||||
|
image: busybox:1.28
|
||||||
|
command: ['sh', '-c', 'echo The app is running! && sleep 30']
|
||||||
|
initContainers:
|
||||||
|
- name: init-whoami
|
||||||
|
image: busybox:1.28
|
||||||
|
command: ['sh', '-c', "until nslookup whoami.\$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for whoami; sleep 2; done"]
|
||||||
|
- name: wait-for-whoami-pods
|
||||||
|
image: ghcr.io/groundnuty/k8s-wait-for:v1.7
|
||||||
|
imagePullPolicy: IfNotPresent
|
||||||
|
args:
|
||||||
|
- "pod-wr"
|
||||||
|
- "-lapp=whoami"
|
||||||
|
EOF
|
||||||
|
|
||||||
|
kubectl scale deployment whoami --replicas=0
|
||||||
|
kubectl apply -f myapp-pod-exists.yaml
|
||||||
|
|
||||||
|
kubectl create role pod-reader \
|
||||||
|
--verb=get --verb=list --verb=watch \
|
||||||
|
--resource=pods,services,deployments
|
||||||
|
|
||||||
|
kubectl get role pod-reader -o yaml
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: Role
|
||||||
|
metadata:
|
||||||
|
creationTimestamp: "2022-10-27T13:11:32Z"
|
||||||
|
name: pod-reader
|
||||||
|
namespace: whoami-1
|
||||||
|
resourceVersion: "48787"
|
||||||
|
uid: 2aadcee7-66bc-4ebe-8acc-5f76e2065480
|
||||||
|
rules:
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- pods
|
||||||
|
- services
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- listhttps://artifacthub.io/
|
||||||
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- apps
|
||||||
|
resources:
|
||||||
|
- deployments
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- watch
|
||||||
|
|
||||||
|
|
||||||
|
kubectl create rolebinding default-pod-reader \
|
||||||
|
--role=pod-reader \
|
||||||
|
--serviceaccount=whoami-1:default \
|
||||||
|
--namespace=whoami-1
|
||||||
|
|
||||||
|
kubectl get rolebindings.rbac.authorization.k8s.io default-pod-reader -o yaml
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: RoleBinding
|
||||||
|
metadata:
|
||||||
|
creationTimestamp: "2022-10-27T13:15:02Z"
|
||||||
|
name: default-pod-reader
|
||||||
|
namespace: whoami-1
|
||||||
|
resourceVersion: "48886"https://artifacthub.io/
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
kind: Role
|
||||||
|
name: pod-reader
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: default
|
||||||
|
namespace: whoami-1
|
||||||
|
|
||||||
|
kubectl auth can-i list deployments.apps \
|
||||||
|
--as system:serviceaccount:whoami-1:default
|
||||||
|
yes
|
||||||
|
kubectl auth can-i create deployments.apps \
|
||||||
|
--as system:serviceaccount:whoami-1:default
|
||||||
|
no
|
||||||
|
|
||||||
|
kubectl scale deployment whoami --replicas=1
|
||||||
|
kubectl logs myapp-pod-exists -c wait-for-whoami-pods
|
||||||
|
[2022-10-27 13:34:14] Waiting for pod -lapp=whoami...
|
||||||
|
[2022-10-27 13:34:16] pod -lapp=whoami is ready.
|
||||||
|
kubectl get pods
|
||||||
|
NAME READY STATUS RESTARTS AGE
|
||||||
|
...
|
||||||
|
myapp-pod-exists 0/1 Completed 1 (36s ago) 31m
|
||||||
|
|
||||||
|
Postgres initContainer
|
||||||
|
|
||||||
|
apiVersion: apps/v1beta1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: webapp
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: webapp
|
||||||
|
spec:
|
||||||
|
volumes:
|
||||||
|
- name: config-volume
|
||||||
|
configMap:
|
||||||
|
name: app-config
|
||||||
|
initContainers:
|
||||||
|
- name: check-db-ready
|
||||||
|
image: postgres:15
|
||||||
|
command: ['sh', '-c',
|
||||||
|
'until pg_isready -h postgres -p 5432;
|
||||||
|
do echo waiting for database; sleep 2; done;']
|
||||||
|
|
||||||
|
Git Sync
|
||||||
|
|
||||||
|
https://github.com/kubernetes/git-sync
|
||||||
|
https://github.com/kubernetes/git-sync/blob/master/docs/ssh.md
|
||||||
|
https://github.com/kubernetes/git-sync/blob/master/docs/kubernetes.md
|
||||||
|
https://www.heise.de/tipps-tricks/SSH-Key-erstellen-so-geht-s-4400280.html
|
||||||
|
|
||||||
|
Challenges:
|
||||||
|
|
||||||
|
Create SSH Key
|
||||||
|
Create local git repo
|
||||||
|
Create a secret with SSH Key
|
||||||
|
Create a pod with git sync initContainer from local repo
|
||||||
|
|
||||||
|
Create SSH Key
|
||||||
|
|
||||||
|
ssh-keygen -t rsa -b 4096 -f ~/.ssh/id_cnbc-rsa
|
||||||
|
# without password...
|
||||||
|
|
||||||
|
Example to use Git Sync
|
||||||
|
|
||||||
|
# make a directory (owned by you) for the volume
|
||||||
|
export DIR="/tmp/git-data"
|
||||||
|
mkdir -p $DIR
|
||||||
|
|
||||||
|
# run the container (as your own UID)
|
||||||
|
|
||||||
|
# run the container
|
||||||
|
docker container run -d \
|
||||||
|
-v $DIR:/tmp/git \
|
||||||
|
-u$(id -u):$(id -g) \
|
||||||
|
k8s.gcr.io/git-sync/git-sync:v4.0.0 \
|
||||||
|
--repo=https://github.com/kubernetes/git-sync \
|
||||||
|
--root=/tmp/git/root \
|
||||||
|
--period=30s
|
||||||
|
|
||||||
|
# run an nginx container to serve the content
|
||||||
|
docker container run -d \
|
||||||
|
-p 8080:80 \
|
||||||
|
-v $DIR:/usr/share/nginx/html \
|
||||||
|
nginx
|
||||||
|
|
||||||
31
k3d/stress/deployment2.yaml
Normal file
31
k3d/stress/deployment2.yaml
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
creationTimestamp: null
|
||||||
|
labels:
|
||||||
|
app: web
|
||||||
|
name: web
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: web
|
||||||
|
strategy: {}
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
creationTimestamp: null
|
||||||
|
labels:
|
||||||
|
app: web
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- image: bee42/whoami:2.2.0
|
||||||
|
name: whoami
|
||||||
|
ports:
|
||||||
|
- containerPort: 80
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
memory: "64Mi"
|
||||||
|
cpu: "250m"
|
||||||
|
limits:
|
||||||
|
memory: "128Mi"
|
||||||
|
cpu: "500m"
|
||||||
274
k3d/stress/doku
Normal file
274
k3d/stress/doku
Normal file
@@ -0,0 +1,274 @@
|
|||||||
|
Deployment with Ressource Constraints
|
||||||
|
|
||||||
|
https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
|
||||||
|
|
||||||
|
It's a good practice to assign a CPU request and a CPU limit to a container. Containers cannot use more CPU than the configured limit. Provided the system has CPU time free, a container is guaranteed to be allocated as much CPU as it requests.
|
||||||
|
|
||||||
|
mkdir ~/stress && cd ~/stress
|
||||||
|
kubectl create namespace stress
|
||||||
|
kubectl config set-context --current --namespace stress
|
||||||
|
|
||||||
|
cat >deployment2.yaml <<EOF
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
creationTimestamp: null
|
||||||
|
labels:
|
||||||
|
app: web
|
||||||
|
name: web
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: web
|
||||||
|
strategy: {}
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
creationTimestamp: null
|
||||||
|
labels:
|
||||||
|
app: web
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- image: bee42/whoami:2.2.0
|
||||||
|
name: whoami
|
||||||
|
ports:
|
||||||
|
- containerPort: 80
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
memory: "64Mi"
|
||||||
|
cpu: "250m"
|
||||||
|
limits:
|
||||||
|
memory: "128Mi"
|
||||||
|
cpu: "500m"
|
||||||
|
EOF
|
||||||
|
|
||||||
|
kubectl apply -f deployment2.yaml
|
||||||
|
kubectl get pods
|
||||||
|
kubectl get all
|
||||||
|
kubectl describe deployment web
|
||||||
|
kubectl rollout history deployment web
|
||||||
|
# set change cause
|
||||||
|
kubectl annotate deployment web kubernetes.io/change-cause='set cpu limit 500'
|
||||||
|
kubectl rollout history deployment web
|
||||||
|
|
||||||
|
https://kubernetes.io/docs/tasks/configure-pod-container/quality-service-pod/
|
||||||
|
QoS
|
||||||
|
https://kubernetes.io/docs/tasks/administer-cluster/manage-resources/quota-pod-namespace/
|
||||||
|
ResoureQuota
|
||||||
|
|
||||||
|
Generate Stress
|
||||||
|
|
||||||
|
https://linux.die.net/man/1/stress
|
||||||
|
|
||||||
|
create your own stress tool
|
||||||
|
|
||||||
|
mkdir -p ~/stress && cd ~/stress
|
||||||
|
cat >Dockerfile <<EOF
|
||||||
|
FROM ubuntu
|
||||||
|
|
||||||
|
RUN apt-get update && apt-get install -y stress && rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
ENTRYPOINT ["/usr/bin/stress", "--verbose"]
|
||||||
|
CMD []
|
||||||
|
EOF
|
||||||
|
docker build -t 127.0.0.1:5000/bee42/stress .
|
||||||
|
docker push 127.0.0.1:5000/bee42/stress
|
||||||
|
|
||||||
|
Todo:
|
||||||
|
|
||||||
|
apply the pod
|
||||||
|
check with kubectl top pods
|
||||||
|
|
||||||
|
cat >pod.yaml <<EOF
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Pod
|
||||||
|
metadata:
|
||||||
|
name: cpu-demo
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: cpu
|
||||||
|
image: cnbc-registry:5000/bee42/stress
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpu: "1"
|
||||||
|
requests:
|
||||||
|
cpu: "0.5"
|
||||||
|
args:
|
||||||
|
- --cpu
|
||||||
|
- "2"
|
||||||
|
EOF
|
||||||
|
kubectl apply -f pod.yaml
|
||||||
|
kubectl describe pod cpu-demo
|
||||||
|
# wait a minute
|
||||||
|
kubectl top pods
|
||||||
|
NAME CPU(cores) MEMORY(bytes)
|
||||||
|
cpu-demo 1962m 1Mi
|
||||||
|
hey 0m 0Mi
|
||||||
|
load 0m 1Mi
|
||||||
|
web-7cdc98f947-2n2dp 0m 3Mi
|
||||||
|
web-7cdc98f947-gn2cg 0m 4Mi
|
||||||
|
|
||||||
|
# Consume more cpu the limits set!
|
||||||
|
|
||||||
|
# PLEASE KILL this pod
|
||||||
|
kubectl delete pod cpu-demo --force=true --grace-period=0
|
||||||
|
|
||||||
|
stress-deploy.yaml
|
||||||
|
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: cpu-demo
|
||||||
|
labels:
|
||||||
|
app: cpu-demo
|
||||||
|
spec:
|
||||||
|
replicas: 4
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: cpu-demo
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: cpu-demo
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: stress
|
||||||
|
image: cnbc-registry:5000/bee42/stress
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpu: "1"
|
||||||
|
requests:
|
||||||
|
cpu: "0.5"
|
||||||
|
args:
|
||||||
|
- --cpu
|
||||||
|
- "2"
|
||||||
|
nodeName: k3d-cnbc-agent-1
|
||||||
|
|
||||||
|
kubectl apply -f stress-deploy.yaml
|
||||||
|
kubectl top pods
|
||||||
|
kubectl top nodes
|
||||||
|
NAME CPU(cores) MEMORY(bytes)
|
||||||
|
cpu-demo-595664dd8-lschw 1022m 1Mi
|
||||||
|
cpu-demo-595664dd8-npx4w 975m 1Mi
|
||||||
|
cpu-demo-595664dd8-p249m 993m 1Mi
|
||||||
|
cpu-demo-595664dd8-twn84 940m 1Mi
|
||||||
|
web-588896757f-52gx9 0m 1Mi
|
||||||
|
|
||||||
|
kubectl scale deploy cpu-demo --replicas=3
|
||||||
|
|
||||||
|
sleep 45
|
||||||
|
|
||||||
|
kubectl top nodes
|
||||||
|
kubectl top pods
|
||||||
|
NAME CPU(cores) MEMORY(bytes)
|
||||||
|
cpu-demo-595664dd8-npx4w 1017m 1Mi
|
||||||
|
cpu-demo-595664dd8-p249m 988m 1Mi
|
||||||
|
cpu-demo-595664dd8-twn84 980m 1Mi
|
||||||
|
web-588896757f-52gx9 1m 1Mi
|
||||||
|
|
||||||
|
https://kubernetes.io/docs/tasks/administer-cluster/cpu-management-policies/
|
||||||
|
Kubelet parameter
|
||||||
|
|
||||||
|
Tipp:
|
||||||
|
|
||||||
|
use imagePullSecerts to auth container registries
|
||||||
|
|
||||||
|
https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/
|
||||||
|
|
||||||
|
Memory Overload
|
||||||
|
|
||||||
|
https://www.cyberciti.biz/faq/stress-test-linux-unix-server-with-stress-ng/
|
||||||
|
https://sysdig.com/blog/troubleshoot-kubernetes-oom/
|
||||||
|
|
||||||
|
k3d node create --cluster cnbc --role agent --memory 2G k3d-cnbc-agent-2
|
||||||
|
kubectl get nodes
|
||||||
|
# wait for ready
|
||||||
|
kubectl apply -f mem-deploy.yaml
|
||||||
|
|
||||||
|
kubectl top nodes
|
||||||
|
# OK!
|
||||||
|
kubectl scale deploy mem-demo --replicas=4
|
||||||
|
|
||||||
|
# Hups...
|
||||||
|
kubectl scale deploy mem-demo --replicas=5
|
||||||
|
# wait 60 secs
|
||||||
|
kubectl get pods -w
|
||||||
|
NAME READY STATUS RESTARTS AGE
|
||||||
|
web-588896757f-52gx9 1/1 Running 0 60m
|
||||||
|
mem-demo-67998d7456-4ntqw 1/1 Running 0 4m20s
|
||||||
|
mem-demo-67998d7456-htvnn 1/1 Running 0 4m20s
|
||||||
|
mem-demo-67998d7456-4f2wd 1/1 Running 0 2m2s
|
||||||
|
mem-demo-67998d7456-kx4xv 1/1 Running 2 (49s ago) 4m20s
|
||||||
|
mem-demo-67998d7456-d86cs 0/1 OOMKilled 2 (25s ago) 58s
|
||||||
|
mem-demo-67998d7456-d86cs 0/1 CrashLoopBackOff 2 (12s ago) 65s
|
||||||
|
mem-demo-67998d7456-d86cs 1/1 Running 3 (28s ago) 81s
|
||||||
|
mem-demo-67998d7456-4ntqw 0/1 OOMKilled 0 4m44s
|
||||||
|
mem-demo-67998d7456-4ntqw 1/1 Running 1 (2s ago) 4m45s
|
||||||
|
mem-demo-67998d7456-4f2wd 0/1 OOMKilled 0 2m29s
|
||||||
|
mem-demo-67998d7456-4f2wd 1/1 Running 1 (2s ago) 2m30s
|
||||||
|
mem-demo-67998d7456-d86cs 0/1 OOMKilled 3 (35s ago) 88s
|
||||||
|
mem-demo-67998d7456-d86cs 0/1 CrashLoopBackOff 3 (12s ago) 99s
|
||||||
|
|
||||||
|
# fix: scale down
|
||||||
|
kubectl scale deploy mem-demo --replicas=4
|
||||||
|
|
||||||
|
# cleanup deploy
|
||||||
|
kubectl delete -f mem-deploy.yaml
|
||||||
|
|
||||||
|
# drain node
|
||||||
|
|
||||||
|
kubectl drain k3d-k3d-cnbc-agent-2-0
|
||||||
|
k3d node delete k3d-k3d-cnbc-agent-2-0
|
||||||
|
kubectl delete node k3d-k3d-cnbc-agent-2-0
|
||||||
|
|
||||||
|
mem-deploy.yaml
|
||||||
|
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: mem-demo
|
||||||
|
labels:
|
||||||
|
app: mem-demo
|
||||||
|
spec:
|
||||||
|
replicas: 3
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: mem-demo
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: mem-demo
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: stress
|
||||||
|
image: cnbc-registry:5000/bee42/stress
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
memory: "500Mi"
|
||||||
|
requests:
|
||||||
|
memory: "128Mi"
|
||||||
|
args:
|
||||||
|
- "-m"
|
||||||
|
- "1"
|
||||||
|
- "--vm-bytes"
|
||||||
|
- "490M"
|
||||||
|
nodeName: k3d-k3d-cnbc-agent-2-0
|
||||||
|
|
||||||
|
Kubernetes Failures
|
||||||
|
|
||||||
|
https://codeberg.org/hjacobs/kubernetes-failure-stories
|
||||||
|
https://medium.com/omio-engineering/cpu-limits-and-aggressive-throttling-in-kubernetes-c5b20bd8a718
|
||||||
|
https://home.robusta.dev/blog/stop-using-cpu-limits
|
||||||
|
|
||||||
|
Best practices for CPU limits and requests on Kubernetes
|
||||||
|
|
||||||
|
Use CPU requests for everything
|
||||||
|
Make sure they are accurate
|
||||||
|
Do not use CPU limits.
|
||||||
|
|
||||||
|
What about memory limits and requests?
|
||||||
|
|
||||||
|
Always use memory limits
|
||||||
|
Always use memory requests
|
||||||
|
Always set your memory requests equal to your limits
|
||||||
|
|
||||||
14
k3d/volumes/pv
Normal file
14
k3d/volumes/pv
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolume
|
||||||
|
metadata:
|
||||||
|
name: task-pv-volume
|
||||||
|
labels:
|
||||||
|
type: local
|
||||||
|
spec:
|
||||||
|
storageClassName: manual
|
||||||
|
capacity:
|
||||||
|
storage: 10Gi
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
hostPath:
|
||||||
|
path: "/mnt/data"
|
||||||
0
k3d/volumes/pvc
Normal file
0
k3d/volumes/pvc
Normal file
10
k8s/carpool/Dockerfile
Normal file
10
k8s/carpool/Dockerfile
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
# syntax=docker/dockerfile:1
|
||||||
|
FROM python:3.8-slim-buster
|
||||||
|
WORKDIR /app
|
||||||
|
COPY requirements.txt requirements.txt
|
||||||
|
RUN pip3 install --disable-pip-version-check -r requirements.txt
|
||||||
|
COPY . .
|
||||||
|
ENV FLASK_APP=python_rest
|
||||||
|
EXPOSE 5000
|
||||||
|
STOPSIGNAL SIGINT
|
||||||
|
CMD [ "python3", "-m" , "flask", "run", "--host=0.0.0.0"]
|
||||||
23
k8s/carpool/deployment.yaml
Normal file
23
k8s/carpool/deployment.yaml
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: carpool
|
||||||
|
labels:
|
||||||
|
app: carpool
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: carpool
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: carpool
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: carpool
|
||||||
|
image: cnbc-registry:5000/bee42/carpool:0.1.0
|
||||||
|
imagePullPolicy: Always
|
||||||
|
env:
|
||||||
|
- name: FLASK_APP
|
||||||
|
value: python_rest
|
||||||
714
k8s/carpool/doku
Normal file
714
k8s/carpool/doku
Normal file
@@ -0,0 +1,714 @@
|
|||||||
|
carpool examples
|
||||||
|
|
||||||
|
mkdir ~/carpool && cd ~/carpool
|
||||||
|
# create app
|
||||||
|
vi python_rest.py
|
||||||
|
vi requirements.txt
|
||||||
|
vi Dockerfile
|
||||||
|
|
||||||
|
python_rest.py
|
||||||
|
|
||||||
|
python_rest.py
|
||||||
|
|
||||||
|
from flask import Flask, request, jsonify
|
||||||
|
from flask_sqlalchemy import SQLAlchemy
|
||||||
|
from flask_marshmallow import Marshmallow, fields
|
||||||
|
from flask_cors import CORS
|
||||||
|
|
||||||
|
# Init app
|
||||||
|
app = Flask(__name__)
|
||||||
|
|
||||||
|
#enable CORS
|
||||||
|
CORS(app)
|
||||||
|
# connect to already existing and running Database
|
||||||
|
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql://postgres:cnbc@postgres:5432/esentricar'
|
||||||
|
|
||||||
|
# not important but otherwise we get a warning every time
|
||||||
|
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
|
||||||
|
|
||||||
|
#Init db
|
||||||
|
db = SQLAlchemy(app)
|
||||||
|
#Init ma
|
||||||
|
ma = Marshmallow(app)
|
||||||
|
|
||||||
|
# Pool Car Class/Model
|
||||||
|
class Pool_Car(db.Model):
|
||||||
|
|
||||||
|
#define table, in our case already existing
|
||||||
|
__tablename__ = 'cars'
|
||||||
|
car_id = db.Column(db.Integer, primary_key=True)
|
||||||
|
license_plate = db.Column(db.String(30), unique=True)
|
||||||
|
car_type = db.Column(db.String(20))
|
||||||
|
fuel = db.Column(db.String(20))
|
||||||
|
number_of_seats =db.Column(db.Integer)
|
||||||
|
|
||||||
|
|
||||||
|
# set class attributes
|
||||||
|
def __init__(self, license_plate, car_type, fuel, number_of_seats):
|
||||||
|
self.license_plate = license_plate
|
||||||
|
self.car_type = car_type
|
||||||
|
self.fuel = fuel
|
||||||
|
self.number_of_seats = number_of_seats
|
||||||
|
|
||||||
|
class Pool_CarSchema(ma.Schema):
|
||||||
|
class Meta:
|
||||||
|
fields = ('car_id','license_plate','car_type','fuel','number_of_seats')
|
||||||
|
|
||||||
|
# Init schema
|
||||||
|
pool_car_schema = Pool_CarSchema()
|
||||||
|
pool_cars_schema = Pool_CarSchema(many=True)
|
||||||
|
|
||||||
|
|
||||||
|
# Create a Pool_Car
|
||||||
|
@app.route('/car', methods=['POST'])
|
||||||
|
def add_pool_car():
|
||||||
|
# Get request data as json
|
||||||
|
car_entity = request.get_json()
|
||||||
|
license_plate= car_entity.get('license_plate')
|
||||||
|
car_type = car_entity.get('car_type')
|
||||||
|
fuel = car_entity.get('fuel')
|
||||||
|
number_of_seats = car_entity.get('number_of_seats')
|
||||||
|
|
||||||
|
new_pool_car = Pool_Car(license_plate, car_type, fuel, number_of_seats)
|
||||||
|
|
||||||
|
db.session.add(new_pool_car)
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
return pool_car_schema.jsonify(new_pool_car)
|
||||||
|
|
||||||
|
# Get car_id,license_plate,car_type of all products of the table
|
||||||
|
@app.route('/car', methods=['GET'])
|
||||||
|
def get_pool_cars():
|
||||||
|
all_pool_cars = Pool_Car.query.all()
|
||||||
|
result = pool_cars_schema.dump(all_pool_cars)
|
||||||
|
car_list= []
|
||||||
|
for item in result:
|
||||||
|
car_details = { "car_id":None, "license_plate":None, "car_type":None}
|
||||||
|
car_details['car_id'] = item['car_id']
|
||||||
|
car_details['license_plate'] = item['license_plate']
|
||||||
|
car_details['car_type'] = item['car_type']
|
||||||
|
car_list.append(car_details)
|
||||||
|
return jsonify(car_list)
|
||||||
|
|
||||||
|
# Get Single Products
|
||||||
|
@app.route('/car/<car_id>', methods=['GET'])
|
||||||
|
def get_pool_car(car_id):
|
||||||
|
pool_car = Pool_Car.query.get(car_id)
|
||||||
|
return pool_car_schema.jsonify(pool_car)
|
||||||
|
|
||||||
|
# Delete Product
|
||||||
|
@app.route('/car/<car_id>', methods=['DELETE'])
|
||||||
|
def delete_pool_car(car_id):
|
||||||
|
pool_car = Pool_Car.query.get(car_id)
|
||||||
|
db.session.delete(pool_car)
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
return pool_car_schema.jsonify(pool_car)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
app.run(debug=True) #port='5002'
|
||||||
|
|
||||||
|
requirements.txt
|
||||||
|
|
||||||
|
requirements.txt
|
||||||
|
|
||||||
|
Flask==1.1.1
|
||||||
|
Flask-Cors==3.0.8
|
||||||
|
flask-marshmallow==0.10.1
|
||||||
|
Flask-SQLAlchemy==2.4.1
|
||||||
|
werkzeug==2.0.2
|
||||||
|
marshmallow==3.2.2
|
||||||
|
SQLAlchemy==1.3.11
|
||||||
|
marshmallow-sqlalchemy==0.19.0
|
||||||
|
psycopg2-binary==2.8.4
|
||||||
|
itsdangerous==2.0.1
|
||||||
|
Jinja2==3.0.3
|
||||||
|
|
||||||
|
Dockerfile
|
||||||
|
|
||||||
|
Dockerfile
|
||||||
|
|
||||||
|
# syntax=docker/dockerfile:1
|
||||||
|
FROM python:3.8-slim-buster
|
||||||
|
WORKDIR /app
|
||||||
|
COPY requirements.txt requirements.txt
|
||||||
|
RUN pip3 install --disable-pip-version-check -r requirements.txt
|
||||||
|
COPY . .
|
||||||
|
ENV FLASK_APP=python_rest
|
||||||
|
EXPOSE 5000
|
||||||
|
STOPSIGNAL SIGINT
|
||||||
|
CMD [ "python3", "-m" , "flask", "run", "--host=0.0.0.0"]
|
||||||
|
|
||||||
|
Build app
|
||||||
|
|
||||||
|
docker build -t bee42/carpool:0.1.0 .
|
||||||
|
curl http://127.0.0.1:5000/v2/_catalog
|
||||||
|
{"repositories":[]}
|
||||||
|
docker tag bee42/carpool:0.1.0 127.0.0.1:5000/bee42/carpool:0.1.0
|
||||||
|
docker push 127.0.0.1:5000/bee42/carpool:0.1.0
|
||||||
|
curl http://127.0.0.1:5000/v2/_catalog
|
||||||
|
{"repositories":["bee42/carpool"]}
|
||||||
|
curl http://127.0.0.1:5000/v2/bee42/carpool/tags/list
|
||||||
|
{"name":"bee42/carpool","tags":["0.1.0"]}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
CarPool Deploy Postgres
|
||||||
|
|
||||||
|
New Kubernetes Manifests:
|
||||||
|
|
||||||
|
Persistence Volume
|
||||||
|
Config Map
|
||||||
|
|
||||||
|
mkdir ~/carpool/postgres && cd ~/carpool/postgres
|
||||||
|
|
||||||
|
# define kubernetes manifests
|
||||||
|
|
||||||
|
postgres-deploy.yaml
|
||||||
|
|
||||||
|
postgres-deploy.yaml
|
||||||
|
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: postgres
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: postgres
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: postgres
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: postgres
|
||||||
|
image: postgres:10.4
|
||||||
|
imagePullPolicy: "IfNotPresent"
|
||||||
|
ports:
|
||||||
|
- containerPort: 5432
|
||||||
|
envFrom:
|
||||||
|
- configMapRef:
|
||||||
|
name: postgres-config
|
||||||
|
volumeMounts:
|
||||||
|
- mountPath: /var/lib/postgresql/data
|
||||||
|
name: postgredb
|
||||||
|
- name: config
|
||||||
|
mountPath: "/docker-entrypoint-initdb.d"
|
||||||
|
readOnly: true
|
||||||
|
volumes:
|
||||||
|
- name: config
|
||||||
|
configMap:
|
||||||
|
name: carpool
|
||||||
|
items:
|
||||||
|
- key: "esentricar.sql"
|
||||||
|
path: "esentricar.sql"
|
||||||
|
- name: postgredb
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: postgres-pv-claim
|
||||||
|
|
||||||
|
postgres-schema-cm.yaml
|
||||||
|
|
||||||
|
postgres-schema-cm.yaml
|
||||||
|
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: carpool
|
||||||
|
data:
|
||||||
|
esentricar.sql: |
|
||||||
|
CREATE DATABASE esentricar;
|
||||||
|
\c esentricar;
|
||||||
|
CREATE TABLE cars (
|
||||||
|
car_id SERIAL PRIMARY KEY,
|
||||||
|
license_plate varchar(30) NOT NULL,
|
||||||
|
car_type varchar(30) NOT NULL,
|
||||||
|
fuel varchar(30) NOT NULL,
|
||||||
|
number_of_seats integer NOT NULL
|
||||||
|
);
|
||||||
|
CREATE UNIQUE INDEX cars_license_plate
|
||||||
|
ON cars (license_plate);
|
||||||
|
|
||||||
|
postgres-config.yaml
|
||||||
|
|
||||||
|
postgres-config.yaml
|
||||||
|
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: postgres-config
|
||||||
|
labels:
|
||||||
|
app: postgres
|
||||||
|
data:
|
||||||
|
POSTGRES_DB: postgresdb
|
||||||
|
POSTGRES_USER: postgres
|
||||||
|
POSTGRES_PASSWORD: cnbc
|
||||||
|
|
||||||
|
postgres-service.yaml
|
||||||
|
|
||||||
|
postgres-service.yaml
|
||||||
|
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: postgres
|
||||||
|
name: postgres
|
||||||
|
spec:
|
||||||
|
ports:
|
||||||
|
- name: postgres
|
||||||
|
port: 5432
|
||||||
|
protocol: TCP
|
||||||
|
targetPort: 5432
|
||||||
|
selector:
|
||||||
|
app: postgres
|
||||||
|
type: ClusterIP
|
||||||
|
|
||||||
|
postgres-pv-claim.yaml
|
||||||
|
|
||||||
|
postgres-pv-claim.yaml
|
||||||
|
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
apiVersion: v1
|
||||||
|
metadata:
|
||||||
|
name: postgres-pv-claim
|
||||||
|
labels:
|
||||||
|
app: postgres
|
||||||
|
spec:
|
||||||
|
storageClassName: local-path
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 1Gi
|
||||||
|
|
||||||
|
Create database
|
||||||
|
|
||||||
|
kubectl create namespace carpool
|
||||||
|
kubectl config set-context --current --namespace=carpool
|
||||||
|
# apply all manifests
|
||||||
|
kubectl apply -f .
|
||||||
|
kubectl get all
|
||||||
|
kubectl get configmaps
|
||||||
|
NAME DATA AGE
|
||||||
|
kube-root-ca.crt 1 21m
|
||||||
|
postgres-config 3 42s
|
||||||
|
carpool 1 42s
|
||||||
|
kubectl get pvc,pv
|
||||||
|
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
|
||||||
|
persistentvolumeclaim/postgres-pv-claim Bound pvc-e6e7ba0f-ff3e-4bfa-be1b-4db6629d027e 1Gi RWO local-path 84s
|
||||||
|
|
||||||
|
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
|
||||||
|
persistentvolume/pvc-e6e7ba0f-ff3e-4bfa-be1b-4db6629d027e 1Gi RWO Delete Bound carpool/postgres-pv-claim local-path 79s
|
||||||
|
kubectl describe pv
|
||||||
|
Name: pvc-e6e7ba0f-ff3e-4bfa-be1b-4db6629d027e
|
||||||
|
Labels: <none>
|
||||||
|
Annotations: pv.kubernetes.io/provisioned-by: rancher.io/local-path
|
||||||
|
Finalizers: [kubernetes.io/pv-protection]
|
||||||
|
StorageClass: local-path
|
||||||
|
Status: Bound
|
||||||
|
Claim: carpool/postgres-pv-claim
|
||||||
|
Reclaim Policy: Delete
|
||||||
|
Access Modes: RWO
|
||||||
|
VolumeMode: Filesystem
|
||||||
|
Capacity: 1Gi
|
||||||
|
Node Affinity:
|
||||||
|
Required Terms:
|
||||||
|
Term 0: kubernetes.io/hostname in [k3d-cnbc-agent-1]
|
||||||
|
Message:
|
||||||
|
Source:
|
||||||
|
Type: HostPath (bare host directory volume)
|
||||||
|
Path: /var/lib/rancher/k3s/storage/pvc-e6e7ba0f-ff3e-4bfa-be1b-4db6629d027e_carpool_postgres-pv-claim
|
||||||
|
HostPathType: DirectoryOrCreate
|
||||||
|
Events: <none>
|
||||||
|
|
||||||
|
kubectl logs postgres-65974d6d58-72vk5
|
||||||
|
The files belonging to this database system will be owned by user "postgres".
|
||||||
|
This user must also own the server process.
|
||||||
|
|
||||||
|
The database cluster will be initialized with locale "en_US.utf8".
|
||||||
|
The default database encoding has accordingly been set to "UTF8".
|
||||||
|
The default text search configuration will be set to "english".
|
||||||
|
|
||||||
|
Data page checksums are disabled.
|
||||||
|
|
||||||
|
fixing permissions on existing directory /var/lib/postgresql/data ... ok
|
||||||
|
creating subdirectories ... ok
|
||||||
|
selecting default max_connections ... 100
|
||||||
|
selecting default shared_buffers ... 128MB
|
||||||
|
selecting dynamic shared memory implementation ... posix
|
||||||
|
creating configuration files ... ok
|
||||||
|
running bootstrap script ... ok
|
||||||
|
performing post-bootstrap initialization ... ok
|
||||||
|
syncing data to disk ... ok
|
||||||
|
|
||||||
|
Success. You can now start the database server using:
|
||||||
|
|
||||||
|
pg_ctl -D /var/lib/postgresql/data -l logfile start
|
||||||
|
|
||||||
|
|
||||||
|
WARNING: enabling "trust" authentication for local connections
|
||||||
|
You can change this by editing pg_hba.conf or using the option -A, or
|
||||||
|
--auth-local and --auth-host, the next time you run initdb.
|
||||||
|
waiting for server to start....2022-03-08 12:30:20.872 UTC [42] LOG: listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
|
||||||
|
2022-03-08 12:30:20.901 UTC [43] LOG: database system was shut down at 2022-03-08 12:30:20 UTC
|
||||||
|
2022-03-08 12:30:20.911 UTC [42] LOG: database system is ready to accept connections
|
||||||
|
done
|
||||||
|
server started
|
||||||
|
CREATE DATABASE
|
||||||
|
|
||||||
|
ALTER ROLE
|
||||||
|
|
||||||
|
|
||||||
|
/usr/local/bin/docker-entrypoint.sh: running /docker-entrypoint-initdb.d/esentricar.sql
|
||||||
|
CREATE DATABASE
|
||||||
|
You are now connected to database "esentricar" as user "postgres".
|
||||||
|
CREATE TABLE
|
||||||
|
CREATE INDEX
|
||||||
|
|
||||||
|
|
||||||
|
2022-03-08 12:30:21.781 UTC [42] LOG: received fast shutdown request
|
||||||
|
waiting for server to shut down....2022-03-08 12:30:21.783 UTC [42] LOG: aborting any active transactions
|
||||||
|
2022-03-08 12:30:21.787 UTC [42] LOG: worker process: logical replication launcher (PID 49) exited with exit code 1
|
||||||
|
2022-03-08 12:30:21.790 UTC [44] LOG: shutting down
|
||||||
|
2022-03-08 12:30:21.820 UTC [42] LOG: database system is shut down
|
||||||
|
done
|
||||||
|
server stopped
|
||||||
|
|
||||||
|
PostgreSQL init process complete; ready for start up.
|
||||||
|
|
||||||
|
2022-03-08 12:30:21.904 UTC [1] LOG: listening on IPv4 address "0.0.0.0", port 5432
|
||||||
|
2022-03-08 12:30:21.904 UTC [1] LOG: listening on IPv6 address "::", port 5432
|
||||||
|
2022-03-08 12:30:21.909 UTC [1] LOG: listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
|
||||||
|
2022-03-08 12:30:21.929 UTC [79] LOG: database system was shut down at 2022-03-08 12:30:21 UTC
|
||||||
|
2022-03-08 12:30:21.938 UTC [1] LOG: database system is ready to accept connections
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Carpool Deploy App
|
||||||
|
|
||||||
|
deploy service
|
||||||
|
create first car
|
||||||
|
|
||||||
|
mkdir ~/carpool/app && cd ~/carpool/app
|
||||||
|
vi deployment.yaml
|
||||||
|
vi service.yaml
|
||||||
|
|
||||||
|
Find name of your local registry cnbc-registry
|
||||||
|
|
||||||
|
docker container ls
|
||||||
|
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||||
|
6f83432dbef0 rancher/k3d-proxy:5.3.0 "/bin/sh -c nginx-pr…" 29 hours ago Up 29 hours 0.0.0.0:8580->80/tcp, :::8580->80/tcp, 0.0.0.0:8543->443/tcp, :::8543->443/tcp, 0.0.0.0:8545->6443/tcp k3d-cnbc-serverlb
|
||||||
|
5f26dbd03241 rancher/k3s:v1.22.6-k3s1 "/bin/k3s agent" 29 hours ago Up 29 hours k3d-cnbc-agent-1
|
||||||
|
24d5876390bd rancher/k3s:v1.22.6-k3s1 "/bin/k3s agent" 29 hours ago Up 29 hours k3d-cnbc-agent-0
|
||||||
|
b5a50e960917 rancher/k3s:v1.22.6-k3s1 "/bin/k3s server --t…" 29 hours ago Up 29 hours k3d-cnbc-server-0
|
||||||
|
8f73928c8294 registry:2 "/entrypoint.sh /etc…" 29 hours ago Up 29 hours 0.0.0.0:5000->5000/tcp cnbc-registry
|
||||||
|
|
||||||
|
deployment.yaml
|
||||||
|
|
||||||
|
deployment.yaml
|
||||||
|
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: carpool
|
||||||
|
labels:
|
||||||
|
app: carpool
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: carpool
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: carpool
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: carpool
|
||||||
|
image: cnbc-registry:5000/bee42/carpool:0.1.0
|
||||||
|
imagePullPolicy: Always
|
||||||
|
env:
|
||||||
|
- name: FLASK_APP
|
||||||
|
value: python_rest
|
||||||
|
|
||||||
|
service.yaml
|
||||||
|
|
||||||
|
service.yaml
|
||||||
|
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: carpool
|
||||||
|
name: carpool
|
||||||
|
spec:
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
port: 5000
|
||||||
|
protocol: TCP
|
||||||
|
targetPort: 5000
|
||||||
|
selector:
|
||||||
|
app: carpool
|
||||||
|
type: ClusterIP
|
||||||
|
|
||||||
|
cd ..
|
||||||
|
sudo apt install -y tree
|
||||||
|
tree .
|
||||||
|
.
|
||||||
|
├── app
|
||||||
|
│ ├── deployment.yaml
|
||||||
|
│ └── service.yaml
|
||||||
|
├── Dockerfile
|
||||||
|
├── postgres
|
||||||
|
│ ├── postgres-config.yaml
|
||||||
|
│ ├── postgres-deploy.yaml
|
||||||
|
│ ├── postgres-pv-claim.yaml
|
||||||
|
│ ├── postgres-schema-cm.yaml
|
||||||
|
│ └── postgres-service.yaml
|
||||||
|
├── python_rest.py
|
||||||
|
└── requirements.txt
|
||||||
|
|
||||||
|
Deploy App carpool
|
||||||
|
|
||||||
|
# create deployment and service manifests
|
||||||
|
kubectl apply -f app
|
||||||
|
kubectl get all
|
||||||
|
NAME READY STATUS RESTARTS AGE
|
||||||
|
pod/postgres-65974d6d58-72vk5 1/1 Running 0 26m
|
||||||
|
pod/carpool-67d9fcf5f4-8cwdg 1/1 Running 0 11s
|
||||||
|
|
||||||
|
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
|
||||||
|
service/postgres ClusterIP 10.43.178.140 <none> 5432/TCP 26m
|
||||||
|
service/carpool ClusterIP 10.43.223.216 <none> 5000/TCP 11s
|
||||||
|
|
||||||
|
NAME READY UP-TO-DATE AVAILABLE AGE
|
||||||
|
deployment.apps/postgres 1/1 1 1 26m
|
||||||
|
deployment.apps/carpool 1/1 1 1 11s
|
||||||
|
|
||||||
|
NAME DESIRED CURRENT READY AGE
|
||||||
|
replicaset.apps/postgres-65974d6d58 1 1 1 26m
|
||||||
|
replicaset.apps/carpool-67d9fcf5f4 1 1 1 11s
|
||||||
|
|
||||||
|
Access app
|
||||||
|
|
||||||
|
kubectl run curl --tty -i --image curlimages/curl -- /bin/sh
|
||||||
|
# check registry access
|
||||||
|
curl cnbc-registry:5000/v2/
|
||||||
|
curl cnbc-registry:5000/v2/_catalog
|
||||||
|
curl http://cnbc-registry:5000/v2/bee42/carpool/tags/list
|
||||||
|
{"repositories":["bee42/carpool"]}
|
||||||
|
# create data
|
||||||
|
cd /tmp
|
||||||
|
cat >car_1.json <<EOF
|
||||||
|
{
|
||||||
|
"license_plate": "BO-PR-72",
|
||||||
|
"car_type": "mini clubman SD",
|
||||||
|
"fuel": "diesel",
|
||||||
|
"number_of_seats": "5"
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
curl -i -X POST http://carpool:5000/car \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
--data-binary "@car_1.json"
|
||||||
|
HTTP/1.0 200 OK
|
||||||
|
Content-Type: application/json
|
||||||
|
Content-Length: 105
|
||||||
|
Access-Control-Allow-Origin: *
|
||||||
|
Server: Werkzeug/2.0.3 Python/3.8.12
|
||||||
|
Date: Tue, 08 Mar 2022 12:57:40 GMT
|
||||||
|
|
||||||
|
{"car_id":1,"car_type":"mini clubman SD","fuel":"diesel","license_plate":"BO-PR-72","number_of_seats":5}
|
||||||
|
# access data
|
||||||
|
curl http://carpool:5000/car
|
||||||
|
[{"car_id":1,"car_type":"mini clubman SD","license_plate":"BO-PR-72"}]
|
||||||
|
|
||||||
|
#check ips nach neustart
|
||||||
|
kubectl get nodes -o wide
|
||||||
|
docker network inspect k3d-cnbc
|
||||||
|
kubectl edit cm -n kube-system coredns
|
||||||
|
NodeHosts: |
|
||||||
|
172.19.0.1 host.k3d.internal
|
||||||
|
172.19.0.6 k3d-cnbc-serverlb
|
||||||
|
172.19.0.3 k3d-cnbc-agent-0
|
||||||
|
172.19.0.2 k3d-cnbc-server-0
|
||||||
|
172.19.0.4 k3d-cnbc-agent-1
|
||||||
|
172.19.0.5 cnbc-registry
|
||||||
|
|
||||||
|
Patch python_rest.py
|
||||||
|
|
||||||
|
Add import
|
||||||
|
get env parameter
|
||||||
|
concat postgres url with env var parameter
|
||||||
|
|
||||||
|
Optimize the App
|
||||||
|
|
||||||
|
no static postgres config
|
||||||
|
define a app configmap
|
||||||
|
|
||||||
|
Edit app
|
||||||
|
|
||||||
|
vi ~/carpool/python_rest.py
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
# Init app
|
||||||
|
app = Flask(__name__)
|
||||||
|
|
||||||
|
user = os.environ.get('POSTGRES_USER', 'postgres')
|
||||||
|
db = os.environ.get('POSTGRES_DB', 'esentricar' )
|
||||||
|
passwd = os.environ.get('POSTGRES_PASSWORD', 'cnbc')
|
||||||
|
host = os.environ.get('POSTGRES_HOST', 'postgres')
|
||||||
|
#enable CORS
|
||||||
|
CORS(app)
|
||||||
|
# connect to already existing and running Database
|
||||||
|
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql://' + user + ':' + passwd + '@' + host + ':5432/' + db
|
||||||
|
|
||||||
|
or patch:
|
||||||
|
|
||||||
|
cat >python_rest.py.patch <<EOF
|
||||||
|
5a6,7
|
||||||
|
> import os
|
||||||
|
>
|
||||||
|
8a11,14
|
||||||
|
> user = os.environ.get('POSTGRES_USER', 'postgres')
|
||||||
|
> db = os.environ.get('POSTGRES_DB', 'esentricar' )
|
||||||
|
> passwd = os.environ.get('POSTGRES_PASSWORD', 'cnbc')
|
||||||
|
> host = os.environ.get('POSTGRES_HOST', 'postgres')
|
||||||
|
12c18
|
||||||
|
< app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql://postgres:cnbc@postgres:5432/esentricar'
|
||||||
|
---
|
||||||
|
> app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql://' + user + ':' + passwd + '@' + host + ':5432/' + db
|
||||||
|
EOF
|
||||||
|
|
||||||
|
patch -p0 < python_rest.py.patch python_rest.py
|
||||||
|
|
||||||
|
docker build -t bee42/carpool:0.2.0 .
|
||||||
|
curl http://127.0.0.1:5000/v2/
|
||||||
|
docker tag bee42/carpool:0.2.0 127.0.0.1:5000/bee42/carpool:0.2.0
|
||||||
|
docker push 127.0.0.1:5000/bee42/carpool:0.2.0
|
||||||
|
curl http://127.0.0.1:5000/v2/bee42/carpool/tags/list
|
||||||
|
{"name":"bee42/carpool","tags":["0.1.0","0.2.0"]}
|
||||||
|
|
||||||
|
app/app-config.yaml
|
||||||
|
|
||||||
|
app-config.yaml
|
||||||
|
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: app-config
|
||||||
|
labels:
|
||||||
|
app: carpool
|
||||||
|
data:
|
||||||
|
POSTGRES_DB: esentricar
|
||||||
|
POSTGRES_PASSWORD: cnbc
|
||||||
|
POSTGRES_USER: postgres
|
||||||
|
POSTGRES_HOST: postgres
|
||||||
|
|
||||||
|
app/deployment.yaml
|
||||||
|
|
||||||
|
deployment.yaml
|
||||||
|
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: carpool
|
||||||
|
labels:
|
||||||
|
app: carpool
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: carpool
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: carpool
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: carpool
|
||||||
|
image: cnbc-registry:5000/bee42/carpool:0.2.0
|
||||||
|
imagePullPolicy: Always
|
||||||
|
env:
|
||||||
|
- name: FLASK_APP
|
||||||
|
value: python_rest
|
||||||
|
envFrom:
|
||||||
|
- configMapRef:
|
||||||
|
name: app-config
|
||||||
|
|
||||||
|
kubectl apply -f app
|
||||||
|
|
||||||
|
# later curl exec
|
||||||
|
kubectl attach -ti curl
|
||||||
|
curl http://carpool:5000/car
|
||||||
|
[{"car_id":1,"car_type":"mini clubman SD","license_plate":"BO-PR-72"}]
|
||||||
|
# remove all
|
||||||
|
kubectl get pv
|
||||||
|
# patch pv if you need the data after redeploy :)
|
||||||
|
|
||||||
|
PV=$(kubectl get pvc -o json -lapp=postgres | jq -r .items[].spec.volumeName)
|
||||||
|
|
||||||
|
kubectl patch pv $PV -p "{\"spec\":{\"persistentVolumeReclaimPolicy\":\"Retain\"}}"
|
||||||
|
|
||||||
|
kubectl delete namespace carpool
|
||||||
|
kubectl create namespace carpool
|
||||||
|
kubectl apply -f postgres
|
||||||
|
kubectl apply -f app
|
||||||
|
|
||||||
|
# Problem: Auto reassociation of pv does't work
|
||||||
|
kubectl get pv
|
||||||
|
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
|
||||||
|
pvc-ab3ea061-9180-4e34-95d5-0100a149747d 1Gi RWO Retain Released carpool/postgres-pv-claim local-path 24m
|
||||||
|
pvc-57cae9ed-3ebe-4181-819a-7a9cfd745606 1Gi RWO Delete Bound carpool/postgres-pv-claim local-path 28s
|
||||||
|
|
||||||
|
kubectl delete namespace carpool
|
||||||
|
kubectl patch pv $PV --type json -p '[{"op": "remove", "path": "/spec/claimRef/uid"}]'
|
||||||
|
kubectl create namespace carpool
|
||||||
|
kubectl apply -f postgres
|
||||||
|
kubectl apply -f app
|
||||||
|
|
||||||
|
Options define a node port services
|
||||||
|
|
||||||
|
cat ~/carpool/app/node-service.yaml <<EOF
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
creationTimestamp: null
|
||||||
|
labels:
|
||||||
|
app: carpool-node
|
||||||
|
name: carpool-node
|
||||||
|
spec:
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
port: 5000
|
||||||
|
protocol: TCP
|
||||||
|
targetPort: 5000
|
||||||
|
selector:
|
||||||
|
app: carpool
|
||||||
|
type: NodePort
|
||||||
|
status:
|
||||||
|
loadBalancer: {}
|
||||||
|
EOF
|
||||||
|
kubectl get nodes -o wide
|
||||||
|
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
|
||||||
|
k3d-cnbc-agent-0 Ready worker 30h v1.22.7+k3s1 172.18.0.4 <none> K3s dev 5.4.0-109-generic containerd://1.5.9-k3s1
|
||||||
|
k3d-cnbc-agent-1 Ready worker 30h v1.22.7+k3s1 172.18.0.3 <none> K3s dev 5.4.0-109-generic containerd://1.5.9-k3s1
|
||||||
|
k3d-cnbc-server-0 Ready control-plane,master 30h v1.22.7+k3s1 172.18.0.2 <none> K3s dev 5.4.0-109-generic containerd://1.5.9-k3s1
|
||||||
|
kubectl apply -f ~/carpool/app/node-service.yaml
|
||||||
|
|
||||||
|
kubectl get service
|
||||||
|
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
|
||||||
|
postgres ClusterIP 10.43.173.36 <none> 5432/TCP 5m37s
|
||||||
|
carpool ClusterIP 10.43.41.38 <none> 5000/TCP 5m11s
|
||||||
|
carpool-node NodePort 10.43.44.24 <none> 5000:31231/TCP 7s
|
||||||
|
|
||||||
|
curl 172.18.0.3:31231/car
|
||||||
|
[{"car_id":1,"car_type":"mini clubman SD","license_plate":"BO-PR-72"}]
|
||||||
|
|
||||||
11
k8s/carpool/esentricar.sql
Normal file
11
k8s/carpool/esentricar.sql
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
CREATE DATABASE esentricar;
|
||||||
|
\c esentricar;
|
||||||
|
CREATE TABLE cars (
|
||||||
|
car_id SERIAL PRIMARY KEY,
|
||||||
|
license_plate varchar(30) NOT NULL,
|
||||||
|
car_type varchar(30) NOT NULL,
|
||||||
|
fuel varchar(30) NOT NULL,
|
||||||
|
number_of_seats integer NOT NULL
|
||||||
|
);
|
||||||
|
CREATE UNIQUE INDEX cars_license_plate
|
||||||
|
ON cars (license_plate);
|
||||||
1
k8s/carpool/index.env
Normal file
1
k8s/carpool/index.env
Normal file
@@ -0,0 +1 @@
|
|||||||
|
POSTGRES_PASSWORD=postgres
|
||||||
10
k8s/carpool/postgres-config.yaml
Normal file
10
k8s/carpool/postgres-config.yaml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: postgres-config
|
||||||
|
labels:
|
||||||
|
app: postgres
|
||||||
|
data:
|
||||||
|
POSTGRES_DB: postgresdb
|
||||||
|
POSTGRES_USER: postgres
|
||||||
|
POSTGRES_PASSWORD: cnbc
|
||||||
39
k8s/carpool/postgres-deploy.yaml
Normal file
39
k8s/carpool/postgres-deploy.yaml
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: postgres
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: postgres
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: postgres
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: postgres
|
||||||
|
image: postgres:10.4
|
||||||
|
imagePullPolicy: "IfNotPresent"
|
||||||
|
ports:
|
||||||
|
- containerPort: 5432
|
||||||
|
envFrom:
|
||||||
|
- configMapRef:
|
||||||
|
name: postgres-config
|
||||||
|
volumeMounts:
|
||||||
|
- mountPath: /var/lib/postgresql/data
|
||||||
|
name: postgredb
|
||||||
|
- name: config
|
||||||
|
mountPath: "/docker-entrypoint-initdb.d"
|
||||||
|
readOnly: true
|
||||||
|
volumes:
|
||||||
|
- name: config
|
||||||
|
configMap:
|
||||||
|
name: carpool
|
||||||
|
items:
|
||||||
|
- key: "esentricar.sql"
|
||||||
|
path: "esentricar.sql"
|
||||||
|
- name: postgredb
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: postgres-pv-claim
|
||||||
13
k8s/carpool/postgres-pv-claim.yaml
Normal file
13
k8s/carpool/postgres-pv-claim.yaml
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
kind: PersistentVolumeClaim
|
||||||
|
apiVersion: v1
|
||||||
|
metadata:
|
||||||
|
name: postgres-pv-claim
|
||||||
|
labels:
|
||||||
|
app: postgres
|
||||||
|
spec:
|
||||||
|
storageClassName: local-path
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 1Gi
|
||||||
17
k8s/carpool/postgres-schema-cm.yaml
Normal file
17
k8s/carpool/postgres-schema-cm.yaml
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: carpool
|
||||||
|
data:
|
||||||
|
esentricar.sql: |
|
||||||
|
CREATE DATABASE esentricar;
|
||||||
|
\c esentricar;
|
||||||
|
CREATE TABLE cars (
|
||||||
|
car_id SERIAL PRIMARY KEY,
|
||||||
|
license_plate varchar(30) NOT NULL,
|
||||||
|
car_type varchar(30) NOT NULL,
|
||||||
|
fuel varchar(30) NOT NULL,
|
||||||
|
number_of_seats integer NOT NULL
|
||||||
|
);
|
||||||
|
CREATE UNIQUE INDEX cars_license_plate
|
||||||
|
ON cars (license_plate);
|
||||||
15
k8s/carpool/postgres-service.yaml
Normal file
15
k8s/carpool/postgres-service.yaml
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: postgres
|
||||||
|
name: postgres
|
||||||
|
spec:
|
||||||
|
ports:
|
||||||
|
- name: postgres
|
||||||
|
port: 5432
|
||||||
|
protocol: TCP
|
||||||
|
targetPort: 5432
|
||||||
|
selector:
|
||||||
|
app: postgres
|
||||||
|
type: ClusterIP
|
||||||
98
k8s/carpool/python_rest.py
Normal file
98
k8s/carpool/python_rest.py
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
from flask import Flask, request, jsonify
|
||||||
|
from flask_sqlalchemy import SQLAlchemy
|
||||||
|
from flask_marshmallow import Marshmallow, fields
|
||||||
|
from flask_cors import CORS
|
||||||
|
|
||||||
|
# Init app
|
||||||
|
app = Flask(__name__)
|
||||||
|
|
||||||
|
#enable CORS
|
||||||
|
CORS(app)
|
||||||
|
# connect to already existing and running Database
|
||||||
|
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql://postgres:cnbc@postgres:5432/esentricar'
|
||||||
|
|
||||||
|
# not important but otherwise we get a warning every time
|
||||||
|
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
|
||||||
|
|
||||||
|
#Init db
|
||||||
|
db = SQLAlchemy(app)
|
||||||
|
#Init ma
|
||||||
|
ma = Marshmallow(app)
|
||||||
|
|
||||||
|
# Pool Car Class/Model
|
||||||
|
class Pool_Car(db.Model):
|
||||||
|
|
||||||
|
#define table, in our case already existing
|
||||||
|
__tablename__ = 'cars'
|
||||||
|
car_id = db.Column(db.Integer, primary_key=True)
|
||||||
|
license_plate = db.Column(db.String(30), unique=True)
|
||||||
|
car_type = db.Column(db.String(20))
|
||||||
|
fuel = db.Column(db.String(20))
|
||||||
|
number_of_seats =db.Column(db.Integer)
|
||||||
|
|
||||||
|
|
||||||
|
# set class attributes
|
||||||
|
def __init__(self, license_plate, car_type, fuel, number_of_seats):
|
||||||
|
self.license_plate = license_plate
|
||||||
|
self.car_type = car_type
|
||||||
|
self.fuel = fuel
|
||||||
|
self.number_of_seats = number_of_seats
|
||||||
|
|
||||||
|
class Pool_CarSchema(ma.Schema):
|
||||||
|
class Meta:
|
||||||
|
fields = ('car_id','license_plate','car_type','fuel','number_of_seats')
|
||||||
|
|
||||||
|
# Init schema
|
||||||
|
pool_car_schema = Pool_CarSchema()
|
||||||
|
pool_cars_schema = Pool_CarSchema(many=True)
|
||||||
|
|
||||||
|
|
||||||
|
# Create a Pool_Car
|
||||||
|
@app.route('/car', methods=['POST'])
|
||||||
|
def add_pool_car():
|
||||||
|
# Get request data as json
|
||||||
|
car_entity = request.get_json()
|
||||||
|
license_plate= car_entity.get('license_plate')
|
||||||
|
car_type = car_entity.get('car_type')
|
||||||
|
fuel = car_entity.get('fuel')
|
||||||
|
number_of_seats = car_entity.get('number_of_seats')
|
||||||
|
|
||||||
|
new_pool_car = Pool_Car(license_plate, car_type, fuel, number_of_seats)
|
||||||
|
|
||||||
|
db.session.add(new_pool_car)
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
return pool_car_schema.jsonify(new_pool_car)
|
||||||
|
|
||||||
|
# Get car_id,license_plate,car_type of all products of the table
|
||||||
|
@app.route('/car', methods=['GET'])
|
||||||
|
def get_pool_cars():
|
||||||
|
all_pool_cars = Pool_Car.query.all()
|
||||||
|
result = pool_cars_schema.dump(all_pool_cars)
|
||||||
|
car_list= []
|
||||||
|
for item in result:
|
||||||
|
car_details = { "car_id":None, "license_plate":None, "car_type":None}
|
||||||
|
car_details['car_id'] = item['car_id']
|
||||||
|
car_details['license_plate'] = item['license_plate']
|
||||||
|
car_details['car_type'] = item['car_type']
|
||||||
|
car_list.append(car_details)
|
||||||
|
return jsonify(car_list)
|
||||||
|
|
||||||
|
# Get Single Products
|
||||||
|
@app.route('/car/<car_id>', methods=['GET'])
|
||||||
|
def get_pool_car(car_id):
|
||||||
|
pool_car = Pool_Car.query.get(car_id)
|
||||||
|
return pool_car_schema.jsonify(pool_car)
|
||||||
|
|
||||||
|
# Delete Product
|
||||||
|
@app.route('/car/<car_id>', methods=['DELETE'])
|
||||||
|
def delete_pool_car(car_id):
|
||||||
|
pool_car = Pool_Car.query.get(car_id)
|
||||||
|
db.session.delete(pool_car)
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
return pool_car_schema.jsonify(pool_car)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
app.run(debug=True) #port='5002'
|
||||||
11
k8s/carpool/requirements.txt
Normal file
11
k8s/carpool/requirements.txt
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
Flask==1.1.1
|
||||||
|
Flask-Cors==3.0.8
|
||||||
|
flask-marshmallow==0.10.1
|
||||||
|
Flask-SQLAlchemy==2.4.1
|
||||||
|
werkzeug==2.0.2
|
||||||
|
marshmallow==3.2.2
|
||||||
|
SQLAlchemy==1.3.11
|
||||||
|
marshmallow-sqlalchemy==0.19.0
|
||||||
|
psycopg2-binary==2.8.4
|
||||||
|
itsdangerous==2.0.1
|
||||||
|
Jinja2==3.0.3
|
||||||
15
k8s/carpool/service.yaml
Normal file
15
k8s/carpool/service.yaml
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: carpool
|
||||||
|
name: carpool
|
||||||
|
spec:
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
port: 5000
|
||||||
|
protocol: TCP
|
||||||
|
targetPort: 5000
|
||||||
|
selector:
|
||||||
|
app: carpool
|
||||||
|
type: ClusterIP
|
||||||
82
k8s/config_map
Normal file
82
k8s/config_map
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
kubectl create deploy nginx --image nginx --dry-run=client -o yaml >nginx-deploy.yaml
|
||||||
|
vi nginx-deploy.yaml
|
||||||
|
# add volume mounts and volumes from configMap
|
||||||
|
|
||||||
|
# create config Map
|
||||||
|
echo Linuxhotel >index.html
|
||||||
|
|
||||||
|
kubectl create configmap htdocs --from-file index.html=index.html --dry-run=client -o yaml >htdocs-cm.yaml
|
||||||
|
|
||||||
|
kubectl -n nginx apply -f htdocs-cm.yaml
|
||||||
|
kubectl -n nginx apply -f nginx-deploy.yaml
|
||||||
|
|
||||||
|
kubectl -n nginx exec -ti nginx-6fc76484c-q8tmd -- /bin/sh
|
||||||
|
# more /usr/share/nginx/html/index.html
|
||||||
|
|
||||||
|
kubectl edit -n nginx cm htdocs
|
||||||
|
# change content
|
||||||
|
apiVersion: v1
|
||||||
|
data:
|
||||||
|
index.html: |
|
||||||
|
Linuxhotel Cloud Native Base Camp
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: htdocs
|
||||||
|
|
||||||
|
# See it change at running pods!
|
||||||
|
|
||||||
|
kubectl -n nginx exec -ti nginx-6fc76484c-q8tmd -- /bin/sh
|
||||||
|
# more /usr/share/nginx/html/index.html
|
||||||
|
Linuxhotel Cloud Native Base Camp
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
htdocs-cm.yaml
|
||||||
|
|
||||||
|
apiVersion: v1
|
||||||
|
data:
|
||||||
|
index.html: |
|
||||||
|
Linuxhotel
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
creationTimestamp: null
|
||||||
|
name: htdocs
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
nginx-deploy.yaml
|
||||||
|
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
creationTimestamp: null
|
||||||
|
labels:
|
||||||
|
app: nginx
|
||||||
|
name: nginx
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: nginx
|
||||||
|
strategy: {}
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
creationTimestamp: null
|
||||||
|
labels:
|
||||||
|
app: nginx
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- image: nginx
|
||||||
|
name: nginx
|
||||||
|
resources: {}
|
||||||
|
volumeMounts:
|
||||||
|
- name: htdocs
|
||||||
|
mountPath: /usr/share/nginx/html
|
||||||
|
volumes:
|
||||||
|
- name: htdocs
|
||||||
|
configMap:
|
||||||
|
name: htdocs
|
||||||
|
status: {}
|
||||||
|
|
||||||
6
k8s/pods
6
k8s/pods
@@ -67,4 +67,8 @@ kubectl get rs -o json |jq -r .items[].metadata.annotations.\"deployment.kuberne
|
|||||||
kubectl get pods
|
kubectl get pods
|
||||||
kubectl get pod <web pod> -o yaml | sed 's/\(image: nginx\):.*$/\1:1.19.3/' | kubectl replace -f -
|
kubectl get pod <web pod> -o yaml | sed 's/\(image: nginx\):.*$/\1:1.19.3/' | kubectl replace -f -
|
||||||
|
|
||||||
#kubectl get pod web-548df7676c-v48kv -o yaml | sed 's/\(image: nginx\):.*$/\1:1.19.4/' | kubectl replace -f - web-548df7676c-rzp7v
|
#kubectl get pod web-548df7676c-v48kv -o yaml | sed 's/\(image: nginx\):.*$/\1:1.19.4/' | kubectl replace -f - web-548df7676c-rzp7v
|
||||||
|
|
||||||
|
curl -i -X POST http://carpool:5000/car \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
--data-binary "@car_2.json"
|
||||||
93
k8s/pvc
Normal file
93
k8s/pvc
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
Retain static PersistentVolumeClaim
|
||||||
|
|
||||||
|
Change Claim to static hostPath volume
|
||||||
|
|
||||||
|
cat >~/carpool/postgres/postgres-pv-claim.yaml <<EOF
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
apiVersion: v1
|
||||||
|
metadata:
|
||||||
|
name: postgres-pv-claim
|
||||||
|
labels:
|
||||||
|
app: postgres
|
||||||
|
spec:
|
||||||
|
storageClassName: ""
|
||||||
|
volumeName: postgres-pv
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 1Gi
|
||||||
|
EOF
|
||||||
|
|
||||||
|
Create static PersistenceVolume
|
||||||
|
|
||||||
|
cat >~/carpool/postgres/postgres-pv.yaml <<EOF
|
||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolume
|
||||||
|
metadata:
|
||||||
|
name: postgres-pv
|
||||||
|
spec:
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
capacity:
|
||||||
|
storage: 1Gi
|
||||||
|
claimRef:
|
||||||
|
name: postgres-pv-claim
|
||||||
|
namespace: carpool
|
||||||
|
hostPath:
|
||||||
|
path: /data
|
||||||
|
type: DirectoryOrCreate
|
||||||
|
nodeAffinity:
|
||||||
|
required:
|
||||||
|
nodeSelectorTerms:
|
||||||
|
- matchExpressions:
|
||||||
|
- key: kubernetes.io/hostname
|
||||||
|
operator: In
|
||||||
|
values:
|
||||||
|
- k3d-cnbc-agent-1
|
||||||
|
persistentVolumeReclaimPolicy: Retain
|
||||||
|
storageClassName: ""
|
||||||
|
volumeMode: Filesystem
|
||||||
|
EOF
|
||||||
|
|
||||||
|
Szenario:
|
||||||
|
|
||||||
|
kubectl delete namespace carpool
|
||||||
|
kubectl delete pv <...>
|
||||||
|
|
||||||
|
kubectl create namespace carpool
|
||||||
|
kubectl apply -f postgres
|
||||||
|
kubectl apply -f app
|
||||||
|
kubectl run curl -ti --image=curlimages/curl -- /bin/sh
|
||||||
|
cd /tmp
|
||||||
|
cat >car_1.json <<EOF
|
||||||
|
{
|
||||||
|
"license_plate": "BO-PR-72",
|
||||||
|
"car_type": "mini clubman SD",
|
||||||
|
"fuel": "diesel",
|
||||||
|
"number_of_seats": "5"
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
curl -i -X POST http://carpool:5000/car \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
--data-binary "@car_1.json"
|
||||||
|
|
||||||
|
curl http://carpool:5000/car
|
||||||
|
exit
|
||||||
|
|
||||||
|
# delete again and check retaining of pv
|
||||||
|
kubectl delete namespace carpool
|
||||||
|
kubectl get pv
|
||||||
|
|
||||||
|
# if not edit Postgres pvc and pod pending
|
||||||
|
|
||||||
|
kubectl edit pv <...>
|
||||||
|
# remove claim-ref uid and resource version
|
||||||
|
kubectl create ns carpool
|
||||||
|
kubectl apply -f postgres
|
||||||
|
kubectl apply -f app
|
||||||
|
kubectl run curl -ti --image=curlimages/curl -- /bin/sh
|
||||||
|
curl http://carpool:5000/car
|
||||||
|
# data exists
|
||||||
|
exit
|
||||||
|
|
||||||
@@ -9,7 +9,6 @@ services:
|
|||||||
- /var/cache/nginx
|
- /var/cache/nginx
|
||||||
- /run
|
- /run
|
||||||
read_only: true
|
read_only: true
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
default:
|
default:
|
||||||
driver: bridge
|
driver: bridge
|
||||||
|
|||||||
152
traefik/doku
Normal file
152
traefik/doku
Normal file
@@ -0,0 +1,152 @@
|
|||||||
|
mkdir ~/traefik && cd ~/traefik
|
||||||
|
helm repo add traefik https://helm.traefik.io/traefik
|
||||||
|
helm repo update
|
||||||
|
helm pull traefik/traefik --untar
|
||||||
|
cd traefik
|
||||||
|
tree .
|
||||||
|
|
||||||
|
.
|
||||||
|
├── Changelog.md
|
||||||
|
├── Chart.yaml
|
||||||
|
├── crds
|
||||||
|
│ ├── ingressroutetcp.yaml
|
||||||
|
│ ├── ingressrouteudp.yaml
|
||||||
|
│ ├── ingressroute.yaml
|
||||||
|
│ ├── middlewarestcp.yaml
|
||||||
|
│ ├── middlewares.yaml
|
||||||
|
│ ├── serverstransports.yaml
|
||||||
|
│ ├── tlsoptions.yaml
|
||||||
|
│ ├── tlsstores.yaml
|
||||||
|
│ └── traefikservices.yaml
|
||||||
|
├── Guidelines.md
|
||||||
|
├── LICENSE
|
||||||
|
├── README.md
|
||||||
|
├── templates
|
||||||
|
│ ├── daemonset.yaml
|
||||||
|
│ ├── dashboard-hook-ingressroute.yaml
|
||||||
|
│ ├── deployment.yaml
|
||||||
|
│ ├── extra-objects.yaml
|
||||||
|
│ ├── gatewayclass.yaml
|
||||||
|
│ ├── gateway.yaml
|
||||||
|
│ ├── _helpers.tpl
|
||||||
|
│ ├── hpa.yaml
|
||||||
|
│ ├── ingressclass.yaml
|
||||||
|
│ ├── poddisruptionbudget.yaml
|
||||||
|
│ ├── _podtemplate.tpl
|
||||||
|
│ ├── pvc.yaml
|
||||||
|
│ ├── rbac
|
||||||
|
│ │ ├── clusterrolebinding.yaml
|
||||||
|
│ │ ├── clusterrole.yaml
|
||||||
|
│ │ ├── podsecuritypolicy.yaml
|
||||||
|
│ │ ├── rolebinding.yaml
|
||||||
|
│ │ ├── role.yaml
|
||||||
|
│ │ └── serviceaccount.yaml
|
||||||
|
│ ├── _service.tpl
|
||||||
|
│ ├── service.yaml
|
||||||
|
│ ├── tlsoption.yaml
|
||||||
|
│ └── tlsstore.yaml
|
||||||
|
└── values.yaml
|
||||||
|
|
||||||
|
3 directories, 37 files
|
||||||
|
|
||||||
|
# install
|
||||||
|
kubectl create ns traefik-v2
|
||||||
|
helm install --namespace=traefik-v2 \
|
||||||
|
traefik traefik/traefik
|
||||||
|
kubectl -n traefik-v2 get all
|
||||||
|
|
||||||
|
cd ../web/
|
||||||
|
|
||||||
|
cat >ingress-values.yaml <<EOF
|
||||||
|
ingress:
|
||||||
|
enabled: true
|
||||||
|
className: ""
|
||||||
|
annotations:
|
||||||
|
kubernetes.io/ingress.class: traefik
|
||||||
|
# kubernetes.io/ingress.class: nginx
|
||||||
|
# kubernetes.io/tls-acme: "true"
|
||||||
|
hosts:
|
||||||
|
- host: web.local
|
||||||
|
paths:
|
||||||
|
- path: /
|
||||||
|
pathType: ImplementationSpecific
|
||||||
|
tls: []
|
||||||
|
# - secretName: chart-example-tls
|
||||||
|
# hosts:
|
||||||
|
# - chart-example.local
|
||||||
|
EOF
|
||||||
|
|
||||||
|
helm template --values ingress-values.yaml --set image.tag=1.21.3 . |more
|
||||||
|
helm upgrade web --values ingress-values.yaml --set image.tag=1.21.3 .
|
||||||
|
curl -H "Host: web.local" http://127.0.0.1:8580
|
||||||
|
|
||||||
|
Beispiel Ingress Manifest
|
||||||
|
|
||||||
|
# Source: web/templates/ingress.yaml
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: release-name-web
|
||||||
|
labels:
|
||||||
|
helm.sh/chart: web-0.1.0
|
||||||
|
app.kubernetes.io/name: web
|
||||||
|
app.kubernetes.io/instance: release-name
|
||||||
|
app.kubernetes.io/version: "1.16.0"
|
||||||
|
app.kubernetes.io/managed-by: Helm
|
||||||
|
annotations:
|
||||||
|
kubernetes.io/ingress.class: traefik
|
||||||
|
spec:
|
||||||
|
rules:
|
||||||
|
- host: "web.local"
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
- path: /
|
||||||
|
pathType: ImplementationSpecific
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: release-name-web
|
||||||
|
port:
|
||||||
|
number: 80
|
||||||
|
|
||||||
|
cat >~/carpool/app/ingress.yaml <<EOF
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: carpool
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: carpool
|
||||||
|
annotations:
|
||||||
|
kubernetes.io/ingress.class: traefik
|
||||||
|
spec:
|
||||||
|
rules:
|
||||||
|
- host: "carpool.local"
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
- path: /
|
||||||
|
pathType: ImplementationSpecific
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: carpool
|
||||||
|
port:
|
||||||
|
number: 5000
|
||||||
|
EOF
|
||||||
|
kubectl apply -n carpool -f ~/carpool/app/ingress.yaml
|
||||||
|
curl -H "Host: carpool.local" http://127.0.0.1:8580/car
|
||||||
|
[{"car_id":1,"car_type":"mini clubman SD","license_plate":"BO-PR-72"}]
|
||||||
|
TRAEFIK_PODNAME=$(kubectl -n traefik-v2 get pods -l app.kubernetes.io/name=traefik -o jsonpath="{range .items[*]}{@.metadata.name}{end}")
|
||||||
|
kubectl -n traefik-v2 port-forward $TRAEFIK_PODNAME 9000:9000 &
|
||||||
|
# open browser http://127.0.0.1:9000/dashboard/
|
||||||
|
|
||||||
|
|
||||||
|
# or
|
||||||
|
|
||||||
|
# cloud instance
|
||||||
|
IP4=$(/sbin/ip -o -4 addr list eth0 | awk '{print $4}' | cut -d/ -f1)
|
||||||
|
# notebook
|
||||||
|
IP4=$(/sbin/ip -o -4 addr list br2 | awk '{print $4}' | cut -d/ -f1
|
||||||
|
|
||||||
|
kubectl -n traefik-v2 port-forward $TRAEFIK_PODNAME --address $IP4 9000:9000 &
|
||||||
|
|
||||||
|
# open browser http://$IP4:9000/dashboard/
|
||||||
|
|
||||||
|
|
||||||
331
traefik/get_helm.sh
Executable file
331
traefik/get_helm.sh
Executable file
@@ -0,0 +1,331 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# Copyright The Helm Authors.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
# The install script is based off of the MIT-licensed script from glide,
|
||||||
|
# the package manager for Go: https://github.com/Masterminds/glide.sh/blob/master/get
|
||||||
|
|
||||||
|
: ${BINARY_NAME:="helm"}
|
||||||
|
: ${USE_SUDO:="true"}
|
||||||
|
: ${DEBUG:="false"}
|
||||||
|
: ${VERIFY_CHECKSUM:="true"}
|
||||||
|
: ${VERIFY_SIGNATURES:="false"}
|
||||||
|
: ${HELM_INSTALL_DIR:="/usr/local/bin"}
|
||||||
|
: ${GPG_PUBRING:="pubring.kbx"}
|
||||||
|
|
||||||
|
HAS_CURL="$(type "curl" &> /dev/null && echo true || echo false)"
|
||||||
|
HAS_WGET="$(type "wget" &> /dev/null && echo true || echo false)"
|
||||||
|
HAS_OPENSSL="$(type "openssl" &> /dev/null && echo true || echo false)"
|
||||||
|
HAS_GPG="$(type "gpg" &> /dev/null && echo true || echo false)"
|
||||||
|
HAS_GIT="$(type "git" &> /dev/null && echo true || echo false)"
|
||||||
|
|
||||||
|
# initArch discovers the architecture for this system.
|
||||||
|
initArch() {
|
||||||
|
ARCH=$(uname -m)
|
||||||
|
case $ARCH in
|
||||||
|
armv5*) ARCH="armv5";;
|
||||||
|
armv6*) ARCH="armv6";;
|
||||||
|
armv7*) ARCH="arm";;
|
||||||
|
aarch64) ARCH="arm64";;
|
||||||
|
x86) ARCH="386";;
|
||||||
|
x86_64) ARCH="amd64";;
|
||||||
|
i686) ARCH="386";;
|
||||||
|
i386) ARCH="386";;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
# initOS discovers the operating system for this system.
|
||||||
|
initOS() {
|
||||||
|
OS=$(echo `uname`|tr '[:upper:]' '[:lower:]')
|
||||||
|
|
||||||
|
case "$OS" in
|
||||||
|
# Minimalist GNU for Windows
|
||||||
|
mingw*|cygwin*) OS='windows';;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
# runs the given command as root (detects if we are root already)
|
||||||
|
runAsRoot() {
|
||||||
|
if [ $EUID -ne 0 -a "$USE_SUDO" = "true" ]; then
|
||||||
|
sudo "${@}"
|
||||||
|
else
|
||||||
|
"${@}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# verifySupported checks that the os/arch combination is supported for
|
||||||
|
# binary builds, as well whether or not necessary tools are present.
|
||||||
|
verifySupported() {
|
||||||
|
local supported="darwin-amd64\ndarwin-arm64\nlinux-386\nlinux-amd64\nlinux-arm\nlinux-arm64\nlinux-ppc64le\nlinux-s390x\nwindows-amd64"
|
||||||
|
if ! echo "${supported}" | grep -q "${OS}-${ARCH}"; then
|
||||||
|
echo "No prebuilt binary for ${OS}-${ARCH}."
|
||||||
|
echo "To build from source, go to https://github.com/helm/helm"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "${HAS_CURL}" != "true" ] && [ "${HAS_WGET}" != "true" ]; then
|
||||||
|
echo "Either curl or wget is required"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "${VERIFY_CHECKSUM}" == "true" ] && [ "${HAS_OPENSSL}" != "true" ]; then
|
||||||
|
echo "In order to verify checksum, openssl must first be installed."
|
||||||
|
echo "Please install openssl or set VERIFY_CHECKSUM=false in your environment."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "${VERIFY_SIGNATURES}" == "true" ]; then
|
||||||
|
if [ "${HAS_GPG}" != "true" ]; then
|
||||||
|
echo "In order to verify signatures, gpg must first be installed."
|
||||||
|
echo "Please install gpg or set VERIFY_SIGNATURES=false in your environment."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if [ "${OS}" != "linux" ]; then
|
||||||
|
echo "Signature verification is currently only supported on Linux."
|
||||||
|
echo "Please set VERIFY_SIGNATURES=false or verify the signatures manually."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "${HAS_GIT}" != "true" ]; then
|
||||||
|
echo "[WARNING] Could not find git. It is required for plugin installation."
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# checkDesiredVersion checks if the desired version is available.
|
||||||
|
checkDesiredVersion() {
|
||||||
|
if [ "x$DESIRED_VERSION" == "x" ]; then
|
||||||
|
# Get tag from release URL
|
||||||
|
local latest_release_url="https://github.com/helm/helm/releases"
|
||||||
|
if [ "${HAS_CURL}" == "true" ]; then
|
||||||
|
TAG=$(curl -Ls $latest_release_url | grep 'href="/helm/helm/releases/tag/v3.[0-9]*.[0-9]*\"' | sed -E 's/.*\/helm\/helm\/releases\/tag\/(v[0-9\.]+)".*/\1/g' | head -1)
|
||||||
|
elif [ "${HAS_WGET}" == "true" ]; then
|
||||||
|
TAG=$(wget $latest_release_url -O - 2>&1 | grep 'href="/helm/helm/releases/tag/v3.[0-9]*.[0-9]*\"' | sed -E 's/.*\/helm\/helm\/releases\/tag\/(v[0-9\.]+)".*/\1/g' | head -1)
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
TAG=$DESIRED_VERSION
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# checkHelmInstalledVersion checks which version of helm is installed and
|
||||||
|
# if it needs to be changed.
|
||||||
|
checkHelmInstalledVersion() {
|
||||||
|
if [[ -f "${HELM_INSTALL_DIR}/${BINARY_NAME}" ]]; then
|
||||||
|
local version=$("${HELM_INSTALL_DIR}/${BINARY_NAME}" version --template="{{ .Version }}")
|
||||||
|
if [[ "$version" == "$TAG" ]]; then
|
||||||
|
echo "Helm ${version} is already ${DESIRED_VERSION:-latest}"
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
echo "Helm ${TAG} is available. Changing from version ${version}."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# downloadFile downloads the latest binary package and also the checksum
|
||||||
|
# for that binary.
|
||||||
|
downloadFile() {
|
||||||
|
HELM_DIST="helm-$TAG-$OS-$ARCH.tar.gz"
|
||||||
|
DOWNLOAD_URL="https://get.helm.sh/$HELM_DIST"
|
||||||
|
CHECKSUM_URL="$DOWNLOAD_URL.sha256"
|
||||||
|
HELM_TMP_ROOT="$(mktemp -dt helm-installer-XXXXXX)"
|
||||||
|
HELM_TMP_FILE="$HELM_TMP_ROOT/$HELM_DIST"
|
||||||
|
HELM_SUM_FILE="$HELM_TMP_ROOT/$HELM_DIST.sha256"
|
||||||
|
echo "Downloading $DOWNLOAD_URL"
|
||||||
|
if [ "${HAS_CURL}" == "true" ]; then
|
||||||
|
curl -SsL "$CHECKSUM_URL" -o "$HELM_SUM_FILE"
|
||||||
|
curl -SsL "$DOWNLOAD_URL" -o "$HELM_TMP_FILE"
|
||||||
|
elif [ "${HAS_WGET}" == "true" ]; then
|
||||||
|
wget -q -O "$HELM_SUM_FILE" "$CHECKSUM_URL"
|
||||||
|
wget -q -O "$HELM_TMP_FILE" "$DOWNLOAD_URL"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# verifyFile verifies the SHA256 checksum of the binary package
|
||||||
|
# and the GPG signatures for both the package and checksum file
|
||||||
|
# (depending on settings in environment).
|
||||||
|
verifyFile() {
|
||||||
|
if [ "${VERIFY_CHECKSUM}" == "true" ]; then
|
||||||
|
verifyChecksum
|
||||||
|
fi
|
||||||
|
if [ "${VERIFY_SIGNATURES}" == "true" ]; then
|
||||||
|
verifySignatures
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# installFile installs the Helm binary.
|
||||||
|
installFile() {
|
||||||
|
HELM_TMP="$HELM_TMP_ROOT/$BINARY_NAME"
|
||||||
|
mkdir -p "$HELM_TMP"
|
||||||
|
tar xf "$HELM_TMP_FILE" -C "$HELM_TMP"
|
||||||
|
HELM_TMP_BIN="$HELM_TMP/$OS-$ARCH/helm"
|
||||||
|
echo "Preparing to install $BINARY_NAME into ${HELM_INSTALL_DIR}"
|
||||||
|
runAsRoot cp "$HELM_TMP_BIN" "$HELM_INSTALL_DIR/$BINARY_NAME"
|
||||||
|
echo "$BINARY_NAME installed into $HELM_INSTALL_DIR/$BINARY_NAME"
|
||||||
|
}
|
||||||
|
|
||||||
|
# verifyChecksum verifies the SHA256 checksum of the binary package.
|
||||||
|
verifyChecksum() {
|
||||||
|
printf "Verifying checksum... "
|
||||||
|
local sum=$(openssl sha1 -sha256 ${HELM_TMP_FILE} | awk '{print $2}')
|
||||||
|
local expected_sum=$(cat ${HELM_SUM_FILE})
|
||||||
|
if [ "$sum" != "$expected_sum" ]; then
|
||||||
|
echo "SHA sum of ${HELM_TMP_FILE} does not match. Aborting."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "Done."
|
||||||
|
}
|
||||||
|
|
||||||
|
# verifySignatures obtains the latest KEYS file from GitHub main branch
|
||||||
|
# as well as the signature .asc files from the specific GitHub release,
|
||||||
|
# then verifies that the release artifacts were signed by a maintainer's key.
|
||||||
|
verifySignatures() {
|
||||||
|
printf "Verifying signatures... "
|
||||||
|
local keys_filename="KEYS"
|
||||||
|
local github_keys_url="https://raw.githubusercontent.com/helm/helm/main/${keys_filename}"
|
||||||
|
if [ "${HAS_CURL}" == "true" ]; then
|
||||||
|
curl -SsL "${github_keys_url}" -o "${HELM_TMP_ROOT}/${keys_filename}"
|
||||||
|
elif [ "${HAS_WGET}" == "true" ]; then
|
||||||
|
wget -q -O "${HELM_TMP_ROOT}/${keys_filename}" "${github_keys_url}"
|
||||||
|
fi
|
||||||
|
local gpg_keyring="${HELM_TMP_ROOT}/keyring.gpg"
|
||||||
|
local gpg_homedir="${HELM_TMP_ROOT}/gnupg"
|
||||||
|
mkdir -p -m 0700 "${gpg_homedir}"
|
||||||
|
local gpg_stderr_device="/dev/null"
|
||||||
|
if [ "${DEBUG}" == "true" ]; then
|
||||||
|
gpg_stderr_device="/dev/stderr"
|
||||||
|
fi
|
||||||
|
gpg --batch --quiet --homedir="${gpg_homedir}" --import "${HELM_TMP_ROOT}/${keys_filename}" 2> "${gpg_stderr_device}"
|
||||||
|
gpg --batch --no-default-keyring --keyring "${gpg_homedir}/${GPG_PUBRING}" --export > "${gpg_keyring}"
|
||||||
|
local github_release_url="https://github.com/helm/helm/releases/download/${TAG}"
|
||||||
|
if [ "${HAS_CURL}" == "true" ]; then
|
||||||
|
curl -SsL "${github_release_url}/helm-${TAG}-${OS}-${ARCH}.tar.gz.sha256.asc" -o "${HELM_TMP_ROOT}/helm-${TAG}-${OS}-${ARCH}.tar.gz.sha256.asc"
|
||||||
|
curl -SsL "${github_release_url}/helm-${TAG}-${OS}-${ARCH}.tar.gz.asc" -o "${HELM_TMP_ROOT}/helm-${TAG}-${OS}-${ARCH}.tar.gz.asc"
|
||||||
|
elif [ "${HAS_WGET}" == "true" ]; then
|
||||||
|
wget -q -O "${HELM_TMP_ROOT}/helm-${TAG}-${OS}-${ARCH}.tar.gz.sha256.asc" "${github_release_url}/helm-${TAG}-${OS}-${ARCH}.tar.gz.sha256.asc"
|
||||||
|
wget -q -O "${HELM_TMP_ROOT}/helm-${TAG}-${OS}-${ARCH}.tar.gz.asc" "${github_release_url}/helm-${TAG}-${OS}-${ARCH}.tar.gz.asc"
|
||||||
|
fi
|
||||||
|
local error_text="If you think this might be a potential security issue,"
|
||||||
|
error_text="${error_text}\nplease see here: https://github.com/helm/community/blob/master/SECURITY.md"
|
||||||
|
local num_goodlines_sha=$(gpg --verify --keyring="${gpg_keyring}" --status-fd=1 "${HELM_TMP_ROOT}/helm-${TAG}-${OS}-${ARCH}.tar.gz.sha256.asc" 2> "${gpg_stderr_device}" | grep -c -E '^\[GNUPG:\] (GOODSIG|VALIDSIG)')
|
||||||
|
if [[ ${num_goodlines_sha} -lt 2 ]]; then
|
||||||
|
echo "Unable to verify the signature of helm-${TAG}-${OS}-${ARCH}.tar.gz.sha256!"
|
||||||
|
echo -e "${error_text}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
local num_goodlines_tar=$(gpg --verify --keyring="${gpg_keyring}" --status-fd=1 "${HELM_TMP_ROOT}/helm-${TAG}-${OS}-${ARCH}.tar.gz.asc" 2> "${gpg_stderr_device}" | grep -c -E '^\[GNUPG:\] (GOODSIG|VALIDSIG)')
|
||||||
|
if [[ ${num_goodlines_tar} -lt 2 ]]; then
|
||||||
|
echo "Unable to verify the signature of helm-${TAG}-${OS}-${ARCH}.tar.gz!"
|
||||||
|
echo -e "${error_text}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "Done."
|
||||||
|
}
|
||||||
|
|
||||||
|
# fail_trap is executed if an error occurs.
|
||||||
|
fail_trap() {
|
||||||
|
result=$?
|
||||||
|
if [ "$result" != "0" ]; then
|
||||||
|
if [[ -n "$INPUT_ARGUMENTS" ]]; then
|
||||||
|
echo "Failed to install $BINARY_NAME with the arguments provided: $INPUT_ARGUMENTS"
|
||||||
|
help
|
||||||
|
else
|
||||||
|
echo "Failed to install $BINARY_NAME"
|
||||||
|
fi
|
||||||
|
echo -e "\tFor support, go to https://github.com/helm/helm."
|
||||||
|
fi
|
||||||
|
cleanup
|
||||||
|
exit $result
|
||||||
|
}
|
||||||
|
|
||||||
|
# testVersion tests the installed client to make sure it is working.
|
||||||
|
testVersion() {
|
||||||
|
set +e
|
||||||
|
HELM="$(command -v $BINARY_NAME)"
|
||||||
|
if [ "$?" = "1" ]; then
|
||||||
|
echo "$BINARY_NAME not found. Is $HELM_INSTALL_DIR on your "'$PATH?'
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
set -e
|
||||||
|
}
|
||||||
|
|
||||||
|
# help provides possible cli installation arguments
|
||||||
|
help () {
|
||||||
|
echo "Accepted cli arguments are:"
|
||||||
|
echo -e "\t[--help|-h ] ->> prints this help"
|
||||||
|
echo -e "\t[--version|-v <desired_version>] . When not defined it fetches the latest release from GitHub"
|
||||||
|
echo -e "\te.g. --version v3.0.0 or -v canary"
|
||||||
|
echo -e "\t[--no-sudo] ->> install without sudo"
|
||||||
|
}
|
||||||
|
|
||||||
|
# cleanup temporary files to avoid https://github.com/helm/helm/issues/2977
|
||||||
|
cleanup() {
|
||||||
|
if [[ -d "${HELM_TMP_ROOT:-}" ]]; then
|
||||||
|
rm -rf "$HELM_TMP_ROOT"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Execution
|
||||||
|
|
||||||
|
#Stop execution on any error
|
||||||
|
trap "fail_trap" EXIT
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Set debug if desired
|
||||||
|
if [ "${DEBUG}" == "true" ]; then
|
||||||
|
set -x
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Parsing input arguments (if any)
|
||||||
|
export INPUT_ARGUMENTS="${@}"
|
||||||
|
set -u
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case $1 in
|
||||||
|
'--version'|-v)
|
||||||
|
shift
|
||||||
|
if [[ $# -ne 0 ]]; then
|
||||||
|
export DESIRED_VERSION="${1}"
|
||||||
|
else
|
||||||
|
echo -e "Please provide the desired version. e.g. --version v3.0.0 or -v canary"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
'--no-sudo')
|
||||||
|
USE_SUDO="false"
|
||||||
|
;;
|
||||||
|
'--help'|-h)
|
||||||
|
help
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
*) exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
set +u
|
||||||
|
|
||||||
|
initArch
|
||||||
|
initOS
|
||||||
|
verifySupported
|
||||||
|
checkDesiredVersion
|
||||||
|
if ! checkHelmInstalledVersion; then
|
||||||
|
downloadFile
|
||||||
|
verifyFile
|
||||||
|
installFile
|
||||||
|
fi
|
||||||
|
testVersion
|
||||||
|
cleanup
|
||||||
23
traefik/web-helm/.helmignore
Normal file
23
traefik/web-helm/.helmignore
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
# Patterns to ignore when building packages.
|
||||||
|
# This supports shell glob matching, relative path matching, and
|
||||||
|
# negation (prefixed with !). Only one pattern per line.
|
||||||
|
.DS_Store
|
||||||
|
# Common VCS dirs
|
||||||
|
.git/
|
||||||
|
.gitignore
|
||||||
|
.bzr/
|
||||||
|
.bzrignore
|
||||||
|
.hg/
|
||||||
|
.hgignore
|
||||||
|
.svn/
|
||||||
|
# Common backup files
|
||||||
|
*.swp
|
||||||
|
*.bak
|
||||||
|
*.tmp
|
||||||
|
*.orig
|
||||||
|
*~
|
||||||
|
# Various IDEs
|
||||||
|
.project
|
||||||
|
.idea/
|
||||||
|
*.tmproj
|
||||||
|
.vscode/
|
||||||
24
traefik/web-helm/Chart.yaml
Normal file
24
traefik/web-helm/Chart.yaml
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
apiVersion: v2
|
||||||
|
name: web-helm
|
||||||
|
description: A Helm chart for Kubernetes
|
||||||
|
|
||||||
|
# A chart can be either an 'application' or a 'library' chart.
|
||||||
|
#
|
||||||
|
# Application charts are a collection of templates that can be packaged into versioned archives
|
||||||
|
# to be deployed.
|
||||||
|
#
|
||||||
|
# Library charts provide useful utilities or functions for the chart developer. They're included as
|
||||||
|
# a dependency of application charts to inject those utilities and functions into the rendering
|
||||||
|
# pipeline. Library charts do not define any templates and therefore cannot be deployed.
|
||||||
|
type: application
|
||||||
|
|
||||||
|
# This is the chart version. This version number should be incremented each time you make changes
|
||||||
|
# to the chart and its templates, including the app version.
|
||||||
|
# Versions are expected to follow Semantic Versioning (https://semver.org/)
|
||||||
|
version: 0.1.0
|
||||||
|
|
||||||
|
# This is the version number of the application being deployed. This version number should be
|
||||||
|
# incremented each time you make changes to the application. Versions are not expected to
|
||||||
|
# follow Semantic Versioning. They should reflect the version the application is using.
|
||||||
|
# It is recommended to use it with quotes.
|
||||||
|
appVersion: "1.16.0"
|
||||||
22
traefik/web-helm/templates/NOTES.txt
Normal file
22
traefik/web-helm/templates/NOTES.txt
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
1. Get the application URL by running these commands:
|
||||||
|
{{- if .Values.ingress.enabled }}
|
||||||
|
{{- range $host := .Values.ingress.hosts }}
|
||||||
|
{{- range .paths }}
|
||||||
|
http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- else if contains "NodePort" .Values.service.type }}
|
||||||
|
export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "web-helm.fullname" . }})
|
||||||
|
export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
|
||||||
|
echo http://$NODE_IP:$NODE_PORT
|
||||||
|
{{- else if contains "LoadBalancer" .Values.service.type }}
|
||||||
|
NOTE: It may take a few minutes for the LoadBalancer IP to be available.
|
||||||
|
You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "web-helm.fullname" . }}'
|
||||||
|
export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "web-helm.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}")
|
||||||
|
echo http://$SERVICE_IP:{{ .Values.service.port }}
|
||||||
|
{{- else if contains "ClusterIP" .Values.service.type }}
|
||||||
|
export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "web-helm.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
|
||||||
|
export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
|
||||||
|
echo "Visit http://127.0.0.1:8080 to use your application"
|
||||||
|
kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT
|
||||||
|
{{- end }}
|
||||||
62
traefik/web-helm/templates/_helpers.tpl
Normal file
62
traefik/web-helm/templates/_helpers.tpl
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
{{/*
|
||||||
|
Expand the name of the chart.
|
||||||
|
*/}}
|
||||||
|
{{- define "web-helm.name" -}}
|
||||||
|
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{/*
|
||||||
|
Create a default fully qualified app name.
|
||||||
|
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
|
||||||
|
If release name contains chart name it will be used as a full name.
|
||||||
|
*/}}
|
||||||
|
{{- define "web-helm.fullname" -}}
|
||||||
|
{{- if .Values.fullnameOverride }}
|
||||||
|
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
|
||||||
|
{{- else }}
|
||||||
|
{{- $name := default .Chart.Name .Values.nameOverride }}
|
||||||
|
{{- if contains $name .Release.Name }}
|
||||||
|
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
|
||||||
|
{{- else }}
|
||||||
|
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{/*
|
||||||
|
Create chart name and version as used by the chart label.
|
||||||
|
*/}}
|
||||||
|
{{- define "web-helm.chart" -}}
|
||||||
|
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{/*
|
||||||
|
Common labels
|
||||||
|
*/}}
|
||||||
|
{{- define "web-helm.labels" -}}
|
||||||
|
helm.sh/chart: {{ include "web-helm.chart" . }}
|
||||||
|
{{ include "web-helm.selectorLabels" . }}
|
||||||
|
{{- if .Chart.AppVersion }}
|
||||||
|
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
|
||||||
|
{{- end }}
|
||||||
|
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{/*
|
||||||
|
Selector labels
|
||||||
|
*/}}
|
||||||
|
{{- define "web-helm.selectorLabels" -}}
|
||||||
|
app.kubernetes.io/name: {{ include "web-helm.name" . }}
|
||||||
|
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{/*
|
||||||
|
Create the name of the service account to use
|
||||||
|
*/}}
|
||||||
|
{{- define "web-helm.serviceAccountName" -}}
|
||||||
|
{{- if .Values.serviceAccount.create }}
|
||||||
|
{{- default (include "web-helm.fullname" .) .Values.serviceAccount.name }}
|
||||||
|
{{- else }}
|
||||||
|
{{- default "default" .Values.serviceAccount.name }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
61
traefik/web-helm/templates/deployment.yaml
Normal file
61
traefik/web-helm/templates/deployment.yaml
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: {{ include "web-helm.fullname" . }}
|
||||||
|
labels:
|
||||||
|
{{- include "web-helm.labels" . | nindent 4 }}
|
||||||
|
spec:
|
||||||
|
{{- if not .Values.autoscaling.enabled }}
|
||||||
|
replicas: {{ .Values.replicaCount }}
|
||||||
|
{{- end }}
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
{{- include "web-helm.selectorLabels" . | nindent 6 }}
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
{{- with .Values.podAnnotations }}
|
||||||
|
annotations:
|
||||||
|
{{- toYaml . | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
labels:
|
||||||
|
{{- include "web-helm.selectorLabels" . | nindent 8 }}
|
||||||
|
spec:
|
||||||
|
{{- with .Values.imagePullSecrets }}
|
||||||
|
imagePullSecrets:
|
||||||
|
{{- toYaml . | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
serviceAccountName: {{ include "web-helm.serviceAccountName" . }}
|
||||||
|
securityContext:
|
||||||
|
{{- toYaml .Values.podSecurityContext | nindent 8 }}
|
||||||
|
containers:
|
||||||
|
- name: {{ .Chart.Name }}
|
||||||
|
securityContext:
|
||||||
|
{{- toYaml .Values.securityContext | nindent 12 }}
|
||||||
|
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
|
||||||
|
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
containerPort: {{ .Values.service.port }}
|
||||||
|
protocol: TCP
|
||||||
|
livenessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /
|
||||||
|
port: http
|
||||||
|
readinessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /
|
||||||
|
port: http
|
||||||
|
resources:
|
||||||
|
{{- toYaml .Values.resources | nindent 12 }}
|
||||||
|
{{- with .Values.nodeSelector }}
|
||||||
|
nodeSelector:
|
||||||
|
{{- toYaml . | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- with .Values.affinity }}
|
||||||
|
affinity:
|
||||||
|
{{- toYaml . | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- with .Values.tolerations }}
|
||||||
|
tolerations:
|
||||||
|
{{- toYaml . | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
28
traefik/web-helm/templates/hpa.yaml
Normal file
28
traefik/web-helm/templates/hpa.yaml
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
{{- if .Values.autoscaling.enabled }}
|
||||||
|
apiVersion: autoscaling/v2beta1
|
||||||
|
kind: HorizontalPodAutoscaler
|
||||||
|
metadata:
|
||||||
|
name: {{ include "web-helm.fullname" . }}
|
||||||
|
labels:
|
||||||
|
{{- include "web-helm.labels" . | nindent 4 }}
|
||||||
|
spec:
|
||||||
|
scaleTargetRef:
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
name: {{ include "web-helm.fullname" . }}
|
||||||
|
minReplicas: {{ .Values.autoscaling.minReplicas }}
|
||||||
|
maxReplicas: {{ .Values.autoscaling.maxReplicas }}
|
||||||
|
metrics:
|
||||||
|
{{- if .Values.autoscaling.targetCPUUtilizationPercentage }}
|
||||||
|
- type: Resource
|
||||||
|
resource:
|
||||||
|
name: cpu
|
||||||
|
targetAverageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if .Values.autoscaling.targetMemoryUtilizationPercentage }}
|
||||||
|
- type: Resource
|
||||||
|
resource:
|
||||||
|
name: memory
|
||||||
|
targetAverageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
61
traefik/web-helm/templates/ingress.yaml
Normal file
61
traefik/web-helm/templates/ingress.yaml
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
{{- if .Values.ingress.enabled -}}
|
||||||
|
{{- $fullName := include "web-helm.fullname" . -}}
|
||||||
|
{{- $svcPort := .Values.service.port -}}
|
||||||
|
{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }}
|
||||||
|
{{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }}
|
||||||
|
{{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}}
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}}
|
||||||
|
apiVersion: networking.k8s.io/v1beta1
|
||||||
|
{{- else -}}
|
||||||
|
apiVersion: extensions/v1beta1
|
||||||
|
{{- end }}
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: {{ $fullName }}
|
||||||
|
labels:
|
||||||
|
{{- include "web-helm.labels" . | nindent 4 }}
|
||||||
|
{{- with .Values.ingress.annotations }}
|
||||||
|
annotations:
|
||||||
|
{{- toYaml . | nindent 4 }}
|
||||||
|
{{- end }}
|
||||||
|
spec:
|
||||||
|
{{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }}
|
||||||
|
ingressClassName: {{ .Values.ingress.className }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if .Values.ingress.tls }}
|
||||||
|
tls:
|
||||||
|
{{- range .Values.ingress.tls }}
|
||||||
|
- hosts:
|
||||||
|
{{- range .hosts }}
|
||||||
|
- {{ . | quote }}
|
||||||
|
{{- end }}
|
||||||
|
secretName: {{ .secretName }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
rules:
|
||||||
|
{{- range .Values.ingress.hosts }}
|
||||||
|
- host: {{ .host | quote }}
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
{{- range .paths }}
|
||||||
|
- path: {{ .path }}
|
||||||
|
{{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }}
|
||||||
|
pathType: {{ .pathType }}
|
||||||
|
{{- end }}
|
||||||
|
backend:
|
||||||
|
{{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }}
|
||||||
|
service:
|
||||||
|
name: {{ $fullName }}
|
||||||
|
port:
|
||||||
|
number: {{ $svcPort }}
|
||||||
|
{{- else }}
|
||||||
|
serviceName: {{ $fullName }}
|
||||||
|
servicePort: {{ $svcPort }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
15
traefik/web-helm/templates/service.yaml
Normal file
15
traefik/web-helm/templates/service.yaml
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: {{ include "web-helm.fullname" . }}
|
||||||
|
labels:
|
||||||
|
{{- include "web-helm.labels" . | nindent 4 }}
|
||||||
|
spec:
|
||||||
|
type: {{ .Values.service.type }}
|
||||||
|
ports:
|
||||||
|
- port: {{ .Values.service.port }}
|
||||||
|
targetPort: http
|
||||||
|
protocol: TCP
|
||||||
|
name: http
|
||||||
|
selector:
|
||||||
|
{{- include "web-helm.selectorLabels" . | nindent 4 }}
|
||||||
12
traefik/web-helm/templates/serviceaccount.yaml
Normal file
12
traefik/web-helm/templates/serviceaccount.yaml
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
{{- if .Values.serviceAccount.create -}}
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ServiceAccount
|
||||||
|
metadata:
|
||||||
|
name: {{ include "web-helm.serviceAccountName" . }}
|
||||||
|
labels:
|
||||||
|
{{- include "web-helm.labels" . | nindent 4 }}
|
||||||
|
{{- with .Values.serviceAccount.annotations }}
|
||||||
|
annotations:
|
||||||
|
{{- toYaml . | nindent 4 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
15
traefik/web-helm/templates/tests/test-connection.yaml
Normal file
15
traefik/web-helm/templates/tests/test-connection.yaml
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Pod
|
||||||
|
metadata:
|
||||||
|
name: "{{ include "web-helm.fullname" . }}-test-connection"
|
||||||
|
labels:
|
||||||
|
{{- include "web-helm.labels" . | nindent 4 }}
|
||||||
|
annotations:
|
||||||
|
"helm.sh/hook": test
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: wget
|
||||||
|
image: busybox
|
||||||
|
command: ['wget']
|
||||||
|
args: ['{{ include "web-helm.fullname" . }}:{{ .Values.service.port }}']
|
||||||
|
restartPolicy: Never
|
||||||
82
traefik/web-helm/values.yaml
Normal file
82
traefik/web-helm/values.yaml
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
# Default values for web-helm.
|
||||||
|
# This is a YAML-formatted file.
|
||||||
|
# Declare variables to be passed into your templates.
|
||||||
|
|
||||||
|
replicaCount: 1
|
||||||
|
|
||||||
|
image:
|
||||||
|
repository: nginx
|
||||||
|
pullPolicy: IfNotPresent
|
||||||
|
# Overrides the image tag whose default is the chart appVersion.
|
||||||
|
tag: ""
|
||||||
|
|
||||||
|
imagePullSecrets: []
|
||||||
|
nameOverride: ""
|
||||||
|
fullnameOverride: ""
|
||||||
|
|
||||||
|
serviceAccount:
|
||||||
|
# Specifies whether a service account should be created
|
||||||
|
create: true
|
||||||
|
# Annotations to add to the service account
|
||||||
|
annotations: {}
|
||||||
|
# The name of the service account to use.
|
||||||
|
# If not set and create is true, a name is generated using the fullname template
|
||||||
|
name: ""
|
||||||
|
|
||||||
|
podAnnotations: {}
|
||||||
|
|
||||||
|
podSecurityContext: {}
|
||||||
|
# fsGroup: 2000
|
||||||
|
|
||||||
|
securityContext: {}
|
||||||
|
# capabilities:
|
||||||
|
# drop:
|
||||||
|
# - ALL
|
||||||
|
# readOnlyRootFilesystem: true
|
||||||
|
# runAsNonRoot: true
|
||||||
|
# runAsUser: 1000
|
||||||
|
|
||||||
|
service:
|
||||||
|
type: ClusterIP
|
||||||
|
port: 80
|
||||||
|
|
||||||
|
ingress:
|
||||||
|
enabled: false
|
||||||
|
className: ""
|
||||||
|
annotations: {}
|
||||||
|
# kubernetes.io/ingress.class: nginx
|
||||||
|
# kubernetes.io/tls-acme: "true"
|
||||||
|
hosts:
|
||||||
|
- host: chart-example.local
|
||||||
|
paths:
|
||||||
|
- path: /
|
||||||
|
pathType: ImplementationSpecific
|
||||||
|
tls: []
|
||||||
|
# - secretName: chart-example-tls
|
||||||
|
# hosts:
|
||||||
|
# - chart-example.local
|
||||||
|
|
||||||
|
resources: {}
|
||||||
|
# We usually recommend not to specify default resources and to leave this as a conscious
|
||||||
|
# choice for the user. This also increases chances charts run on environments with little
|
||||||
|
# resources, such as Minikube. If you do want to specify resources, uncomment the following
|
||||||
|
# lines, adjust them as necessary, and remove the curly braces after 'resources:'.
|
||||||
|
# limits:
|
||||||
|
# cpu: 100m
|
||||||
|
# memory: 128Mi
|
||||||
|
# requests:
|
||||||
|
# cpu: 100m
|
||||||
|
# memory: 128Mi
|
||||||
|
|
||||||
|
autoscaling:
|
||||||
|
enabled: false
|
||||||
|
minReplicas: 1
|
||||||
|
maxReplicas: 100
|
||||||
|
targetCPUUtilizationPercentage: 80
|
||||||
|
# targetMemoryUtilizationPercentage: 80
|
||||||
|
|
||||||
|
nodeSelector: {}
|
||||||
|
|
||||||
|
tolerations: []
|
||||||
|
|
||||||
|
affinity: {}
|
||||||
Reference in New Issue
Block a user