logging node name for important operations
terminating application when watching pods stops Dockerfile and docker compose file added. helm chart added
This commit is contained in:
parent
e8d4adaf53
commit
be5ceb1ee5
23
Dockerfile
Normal file
23
Dockerfile
Normal file
@ -0,0 +1,23 @@
|
||||
|
||||
FROM alpine:3.20.3 as builder
|
||||
|
||||
RUN apk update && apk add go
|
||||
RUN mkdir -p /opt/fetcher/bin
|
||||
WORKDIR /opt/fetcher
|
||||
|
||||
ENV CGO_ENABLED=0
|
||||
ENV GOTOOLCHAIN=auto
|
||||
|
||||
COPY go.mod go.sum /opt/fetcher/
|
||||
RUN go mod download
|
||||
COPY cmd /opt/fetcher/cmd/
|
||||
|
||||
RUN go build -o bin ./cmd/...
|
||||
RUN find . -type f
|
||||
|
||||
|
||||
FROM alpine:3.20.3
|
||||
|
||||
RUN apk update && apk add ca-certificates
|
||||
COPY --from=builder /opt/fetcher/bin/fetcher /opt/fetcher/bin/
|
||||
ENTRYPOINT ["/opt/fetcher/bin/fetcher" ]
|
@ -8,7 +8,6 @@ import (
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/klog/v2"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
@ -28,54 +27,30 @@ func NewFetcher(clientset *kubernetes.Clientset, config *Config, watcher *Watche
|
||||
}
|
||||
|
||||
func (fetcher *Fetcher) canonicalizeImageName(image string) string {
|
||||
pattern := `^(?:(?P<registry>[a-zA-Z0-9][-a-zA-Z0-9.]*[a-zA-Z0-9](?::[0-9]+)?)/)?(?P<repository>(?:[a-z0-9]+(?:(?:[._]|__|[-]+)[a-z0-9]+)*(?:/[a-z0-9]+(?:(?:[._]|__|[-]+)[a-z0-9]+)*)*)?)?(?::(?P<tag>[\w][\w.-]{0,127}))?(?:@(?P<digest>[a-z][a-z0-9]*(?:[+.-][a-z][a-z0-9]*)*:[a-zA-Z0-9*+,-./:;=@_]{32,}))?$`
|
||||
re := regexp.MustCompile(pattern)
|
||||
matches := re.FindStringSubmatch(image)
|
||||
subexpNames := re.SubexpNames()
|
||||
|
||||
if matches == nil {
|
||||
panic(fmt.Errorf("Invalid image reference: %s\n", image))
|
||||
parts := strings.Split(image, "/")
|
||||
if len(parts) < 1 {
|
||||
panic(fmt.Errorf("Could not disect image name '%s'", image))
|
||||
}
|
||||
result := make(map[string]string)
|
||||
for i, name := range subexpNames {
|
||||
if i != 0 && name != "" && i < len(matches) {
|
||||
result[name] = matches[i]
|
||||
}
|
||||
if len(parts) == 1 {
|
||||
parts = []string{"docker.io", "library", parts[0]}
|
||||
}
|
||||
klog.V(3).Infof("Image: %s\n", image)
|
||||
klog.V(3).Infof(" Registry: %s\n", result["registry"])
|
||||
klog.V(3).Infof(" Repository: %s\n", result["repository"])
|
||||
klog.V(3).Infof(" Tag: %s\n", result["tag"])
|
||||
klog.V(3).Infof(" Digest: %s\n", result["digest"])
|
||||
|
||||
registry := result["registry"]
|
||||
repository := result["repository"]
|
||||
tag := result["tag"]
|
||||
digest := result["digest"]
|
||||
|
||||
// Check if image has a tag
|
||||
if digest == "" && tag == "" {
|
||||
tag = "latest"
|
||||
if !strings.Contains(parts[len(parts)-1], ":") {
|
||||
parts[len(parts)-1] = parts[len(parts)-1] + ":latest"
|
||||
}
|
||||
|
||||
// Check if image has a host
|
||||
if registry == "" {
|
||||
registry := ""
|
||||
if strings.Contains(parts[0], ".") {
|
||||
registry = parts[0]
|
||||
parts = parts[1:]
|
||||
} else {
|
||||
registry = "docker.io"
|
||||
}
|
||||
|
||||
// Handle the case when remainder doesn't specify library but it's not a docker.io official image
|
||||
if registry == "docker.io" && !strings.Contains(repository, "/") {
|
||||
repository = "library/" + repository
|
||||
if registry == "docker.io" && len(parts) == 1 {
|
||||
parts[0] = "library/" + parts[0]
|
||||
}
|
||||
|
||||
fullimage := registry + "/" + repository
|
||||
if tag != "" {
|
||||
fullimage += ":" + tag
|
||||
}
|
||||
if digest != "" {
|
||||
fullimage += "@" + digest
|
||||
}
|
||||
return fullimage
|
||||
return registry + "/" + strings.Join(parts, "/")
|
||||
}
|
||||
|
||||
func (fetcher *Fetcher) wasReady(pod *v1.Pod, controllers map[string]bool) bool {
|
||||
@ -135,6 +110,11 @@ func (fetcher *Fetcher) getContainers(clientset *kubernetes.Clientset) map[strin
|
||||
|
||||
func (fetcher *Fetcher) pullAndPin() error {
|
||||
|
||||
nodeName := os.Getenv("NODE_NAME")
|
||||
if nodeName == "" {
|
||||
nodeName = "UNKNOWN"
|
||||
}
|
||||
|
||||
// Create the image manager
|
||||
containerd, err := NewContainerd(fetcher.config.SocketPath, fetcher.config.ContainerdNamespace)
|
||||
if err != nil {
|
||||
@ -154,7 +134,7 @@ func (fetcher *Fetcher) pullAndPin() error {
|
||||
// unpin images that are not used
|
||||
for container, pinned := range imgs {
|
||||
if !containers[container] && pinned {
|
||||
klog.Infof("Unpinning %s\n", container)
|
||||
klog.Infof("%s: Unpinning %s\n", nodeName, container)
|
||||
err := containerd.Unpin(container)
|
||||
if err != nil {
|
||||
klog.Warningf(" error: %v", err)
|
||||
@ -165,7 +145,7 @@ func (fetcher *Fetcher) pullAndPin() error {
|
||||
// Pull images that are used
|
||||
for container := range containers {
|
||||
if _, found := imgs[container]; !found {
|
||||
klog.Infof("Pulling %s\n", container)
|
||||
klog.Infof("%s: Pulling %s\n", nodeName, container)
|
||||
err := containerd.Pull(container)
|
||||
if err != nil {
|
||||
klog.Warningf("error: %v", err)
|
||||
@ -181,7 +161,7 @@ func (fetcher *Fetcher) pullAndPin() error {
|
||||
// Pin images that are used and present
|
||||
for container := range containers {
|
||||
if pinned, found := imgs[container]; found && !pinned {
|
||||
klog.Infof("Pinning %s\n", container)
|
||||
klog.Infof("%s: Pinning %s\n", nodeName, container)
|
||||
err := containerd.Pin(container)
|
||||
if err != nil {
|
||||
klog.Warningf(" error: %v", err)
|
||||
|
@ -95,8 +95,10 @@ func (watcher *Watcher) watchPods(
|
||||
|
||||
_, controller := cache.NewInformerWithOptions(options)
|
||||
stop := make(chan struct{})
|
||||
defer close(stop)
|
||||
go controller.Run(stop)
|
||||
go func() {
|
||||
controller.Run(stop)
|
||||
panic(fmt.Errorf("Watching for pod changes stopped"))
|
||||
}()
|
||||
// Wait for the cache to sync
|
||||
if !cache.WaitForCacheSync(stop, controller.HasSynced) {
|
||||
panic(fmt.Errorf("failed to sync cache"))
|
||||
|
10
compose.yaml
Normal file
10
compose.yaml
Normal file
@ -0,0 +1,10 @@
|
||||
|
||||
services:
|
||||
|
||||
kube-fetcher:
|
||||
image: $REGISTRY/kube-fetcher:1.0.0
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
|
||||
|
39
helm/templates/daemonset.yaml
Normal file
39
helm/templates/daemonset.yaml
Normal file
@ -0,0 +1,39 @@
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: DaemonSet
|
||||
metadata:
|
||||
name: kube-fetcher
|
||||
namespace: {{ .Release.Namespace }}
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
app: kube-fetcher
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: kube-fetcher
|
||||
spec:
|
||||
serviceAccountName: kube-fetcher
|
||||
containers:
|
||||
- name: fetcher
|
||||
image: cat.wamblee.org/kube-fetcher:1.0.0
|
||||
imagePullPolicy: Always
|
||||
env:
|
||||
- name: NODE_NAME
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: spec.nodeName
|
||||
securityContext:
|
||||
privileged: true
|
||||
runAsUser: 0
|
||||
args:
|
||||
- --ready-duration=1m
|
||||
- --v=3
|
||||
volumeMounts:
|
||||
- mountPath: /run/containerd/containerd.sock
|
||||
name: containerd-sock
|
||||
volumes:
|
||||
- name: containerd-sock
|
||||
hostPath:
|
||||
path: /run/containerd/containerd.sock
|
||||
type: Socket
|
32
helm/templates/sa.yaml
Normal file
32
helm/templates/sa.yaml
Normal file
@ -0,0 +1,32 @@
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: kube-fetcher
|
||||
namespace: {{ .Release.Namespace }}
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: kube-fetcher
|
||||
rules:
|
||||
- apiGroups: [""]
|
||||
resources: ["pods"]
|
||||
verbs: ["get", "list", "watch"]
|
||||
- apiGroups: [""]
|
||||
resources: ["nodes"]
|
||||
verbs: ["get", "list"]
|
||||
---
|
||||
# ClusterRoleBinding to connect the ServiceAccount to the ClusterRole
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: kube-fetcher
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: kube-fetcher
|
||||
namespace: {{ .Release.Namespace }}
|
||||
roleRef:
|
||||
kind: ClusterRole
|
||||
name: kube-fetcher
|
||||
apiGroup: rbac.authorization.k8s.io
|
Loading…
Reference in New Issue
Block a user