这是indexloc提供的服务,不要输入任何密码
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions docs/deployment/schedulers/k3s.md
Original file line number Diff line number Diff line change
Expand Up @@ -568,6 +568,11 @@ This plugin implements various functionality through `plugn` triggers to integra
- `apps:clone`
- `apps:destroy`
- `apps:rename`
- `docker-options`:
- The following docker options are translated into their kubernetes equivalents:
- `--cap-add`
- `--cap-drop`
- `--privileged`
- `cron`
- `enter`
- `deploy`
Expand Down
56 changes: 56 additions & 0 deletions plugins/docker-options/dockeroptions.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import (
"os"
"sort"
"strings"

"github.com/dokku/dokku/plugins/common"
)

// SetDockerOptionForPhases sets an option to specified phases
Expand Down Expand Up @@ -85,3 +87,57 @@ func GetDockerOptionsForPhase(appName string, phase string) ([]string, error) {

return options, nil
}

// GetSpecifiedDockerOptionsForPhase returns the docker options for the specified phase that are in the desiredOptions list
// It expects desiredOptions to be a list of docker options that are in the format "--option"
// And will retrieve any lines that start with the desired option
func GetSpecifiedDockerOptionsForPhase(appName string, phase string, desiredOptions []string) (map[string][]string, error) {
foundOptions := map[string][]string{}
options, err := GetDockerOptionsForPhase(appName, phase)
if err != nil {
return foundOptions, err
}

for _, option := range options {
for _, desiredOption := range desiredOptions {
if option == desiredOption {
foundOptions[desiredOption] = []string{}
break
}

// match options that are in the format "--option=value"
if strings.HasPrefix(option, fmt.Sprintf("%s=", desiredOption)) {
if _, ok := foundOptions[desiredOption]; !ok {
foundOptions[desiredOption] = []string{}
}

parts := strings.SplitN(option, "=", 2)
if len(parts) != 2 {
common.LogWarn(fmt.Sprintf("Invalid docker option found for %s: %s", appName, option))
continue
}

foundOptions[desiredOption] = append(foundOptions[desiredOption], parts[1])
break
}

// match options that are in the format "--option value"
if strings.HasPrefix(option, fmt.Sprintf("%s ", desiredOption)) {
if _, ok := foundOptions[desiredOption]; !ok {
foundOptions[desiredOption] = []string{}
}

parts := strings.SplitN(option, " ", 2)
if len(parts) != 2 {
common.LogWarn(fmt.Sprintf("Invalid docker option found for %s: %s", appName, option))
continue
}

foundOptions[desiredOption] = append(foundOptions[desiredOption], parts[1])
break
}
}
}

return foundOptions, nil
}
32 changes: 32 additions & 0 deletions plugins/scheduler-k3s/functions.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (

appjson "github.com/dokku/dokku/plugins/app-json"
"github.com/dokku/dokku/plugins/common"
dockeroptions "github.com/dokku/dokku/plugins/docker-options"
"github.com/dokku/dokku/plugins/logs"
nginxvhosts "github.com/dokku/dokku/plugins/nginx-vhosts"
resty "github.com/go-resty/resty/v2"
Expand Down Expand Up @@ -1489,6 +1490,37 @@ func getStartCommand(input StartCommandInput) (StartCommandOutput, error) {
}, nil
}

func getSecurityContext(appName string, phase string) (SecurityContext, error) {
securityContext := SecurityContext{}
deployOptions, err := dockeroptions.GetSpecifiedDockerOptionsForPhase(appName, phase, []string{
"--cap-add",
"--cap-drop",
"--privileged",
})
if err != nil {
return SecurityContext{}, fmt.Errorf("Error getting deploy options: %w", err)
}

if _, ok := deployOptions["--privileged"]; ok {
securityContext.Privileged = true
}
if capAdd, ok := deployOptions["--cap-add"]; ok {
capabilities := []string{}
for _, cap := range capAdd {
capabilities = append(capabilities, strings.ToUpper(cap))
}
securityContext.Capabilities.Add = capabilities
}
if capDrop, ok := deployOptions["--cap-drop"]; ok {
capabilities := []string{}
for _, cap := range capDrop {
capabilities = append(capabilities, strings.ToUpper(cap))
}
securityContext.Capabilities.Drop = capabilities
}
return securityContext, nil
}

func getProcessSpecificKustomizeRootPath(appName string) string {
if !hasKustomizeDirectory(appName) {
return ""
Expand Down
71 changes: 58 additions & 13 deletions plugins/scheduler-k3s/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package scheduler_k3s
import (
"crypto/rand"
"fmt"
"maps"
"os"
"strings"

Expand Down Expand Up @@ -41,15 +42,16 @@ type AppValues struct {
}

type GlobalValues struct {
Annotations ProcessAnnotations `yaml:"annotations,omitempty"`
AppName string `yaml:"app_name"`
DeploymentID string `yaml:"deployment_id"`
Image GlobalImage `yaml:"image"`
Labels ProcessLabels `yaml:"labels,omitempty"`
Keda GlobalKedaValues `yaml:"keda"`
Namespace string `yaml:"namespace"`
Network GlobalNetwork `yaml:"network"`
Secrets map[string]string `yaml:"secrets,omitempty"`
Annotations ProcessAnnotations `yaml:"annotations,omitempty"`
AppName string `yaml:"app_name"`
DeploymentID string `yaml:"deployment_id"`
Image GlobalImage `yaml:"image"`
Labels ProcessLabels `yaml:"labels,omitempty"`
Keda GlobalKedaValues `yaml:"keda"`
Namespace string `yaml:"namespace"`
Network GlobalNetwork `yaml:"network"`
Secrets map[string]string `yaml:"secrets,omitempty"`
SecurityContext SecurityContext `yaml:"security_context,omitempty"`
}

type GlobalImage struct {
Expand Down Expand Up @@ -351,11 +353,53 @@ type Job struct {
Namespace string
ProcessType string
Schedule string
SecurityContext SecurityContext
Suffix string
RemoveContainer bool
WorkingDir string
}

// SecurityContext contains the security context for a process
type SecurityContext struct {
// Capabilities contains the capabilities for a process
Capabilities SecurityContextCapabilities `yaml:"capabilities,omitempty"`
// Privileged contains the privileged flag for a process
Privileged bool `yaml:"privileged,omitempty"`
}

// ToCoreV1SecurityContext converts the security context to a corev1.SecurityContext
func (s SecurityContext) ToCoreV1SecurityContext() corev1.SecurityContext {
securityContext := corev1.SecurityContext{
Capabilities: &corev1.Capabilities{},
Privileged: ptr.To(s.Privileged),
}

if len(s.Capabilities.Add) > 0 {
capabilities := make([]corev1.Capability, len(s.Capabilities.Add))
for i, cap := range s.Capabilities.Add {
capabilities[i] = corev1.Capability(cap)
}
securityContext.Capabilities.Add = capabilities
}
if len(s.Capabilities.Drop) > 0 {
capabilities := make([]corev1.Capability, len(s.Capabilities.Drop))
for i, cap := range s.Capabilities.Drop {
capabilities[i] = corev1.Capability(cap)
}
securityContext.Capabilities.Drop = capabilities
}

return securityContext
}

// SecurityContextCapabilities contains the capabilities for a process
type SecurityContextCapabilities struct {
// Add contains the add capabilities for a process
Add []string `yaml:"add,omitempty"`
// Drop contains the drop capabilities for a process
Drop []string `yaml:"drop,omitempty"`
}

func templateKubernetesJob(input Job) (batchv1.Job, error) {
labels := map[string]string{
"app.kubernetes.io/instance": fmt.Sprintf("%s-%s", input.AppName, input.ProcessType),
Expand All @@ -368,9 +412,7 @@ func templateKubernetesJob(input Job) (batchv1.Job, error) {
"dokku.com/managed": "true",
}

for key, value := range input.Labels {
labels[key] = value
}
maps.Copy(labels, input.Labels)
secretName := fmt.Sprintf("env-%s.%d", input.AppName, input.DeploymentID)

env := []corev1.EnvVar{}
Expand Down Expand Up @@ -417,6 +459,8 @@ func templateKubernetesJob(input Job) (batchv1.Job, error) {
podAnnotations[key] = value
}

securityContext := input.SecurityContext.ToCoreV1SecurityContext()

job := batchv1.Job{
ObjectMeta: metav1.ObjectMeta{
Name: fmt.Sprintf("%s-%s-%s", input.AppName, input.ProcessType, suffix),
Expand Down Expand Up @@ -453,7 +497,8 @@ func templateKubernetesJob(input Job) (batchv1.Job, error) {
Limits: corev1.ResourceList{},
Requests: corev1.ResourceList{},
},
WorkingDir: input.WorkingDir,
SecurityContext: &securityContext,
WorkingDir: input.WorkingDir,
},
},
RestartPolicy: corev1.RestartPolicyNever,
Expand Down
21 changes: 21 additions & 0 deletions plugins/scheduler-k3s/templates/chart/cron-job.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,27 @@ spec:
{{- end }}
{{- end }}
{{- end }}
{{- if hasKey $.Values.global "security_context" }}
securityContext:
{{- if $.Values.global.security_context.privileged }}
privileged: true
{{- end }}
{{- if hasKey $.Values.global.security_context "capabilities" }}
capabilities:
{{- if hasKey $.Values.global.security_context.capabilities "add" }}
add:
{{- range $.Values.global.security_context.capabilities.add }}
- {{ . }}
{{- end }}
{{- end }}
{{- if hasKey $.Values.global.security_context.capabilities "drop" }}
drop:
{{- range $.Values.global.security_context.capabilities.drop }}
- {{ . }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}
{{- if $.Values.global.image.working_dir }}
workingDir: {{ $.Values.global.image.working_dir }}
{{- end }}
Expand Down
21 changes: 21 additions & 0 deletions plugins/scheduler-k3s/templates/chart/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,27 @@ spec:
readinessProbe:
{{ $config.healthchecks.readiness | toJson | indent 10 }}
{{- end }}
{{- if hasKey $.Values.global "security_context" }}
securityContext:
{{- if $.Values.global.security_context.privileged }}
privileged: true
{{- end }}
{{- if hasKey $.Values.global.security_context "capabilities" }}
capabilities:
{{- if hasKey $.Values.global.security_context.capabilities "add" }}
add:
{{- range $.Values.global.security_context.capabilities.add }}
- {{ . }}
{{- end }}
{{- end }}
{{- if hasKey $.Values.global.security_context.capabilities "drop" }}
drop:
{{- range $.Values.global.security_context.capabilities.drop }}
- {{ . }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}
{{- if $.Values.global.image.working_dir }}
workingDir: {{ $.Values.global.image.working_dir }}
{{- end }}
Expand Down
14 changes: 13 additions & 1 deletion plugins/scheduler-k3s/triggers.go
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,11 @@ func TriggerSchedulerDeploy(scheduler string, appName string, imageTag string) e
return fmt.Errorf("Error getting keda values: %w", err)
}

securityContext, err := getSecurityContext(appName, "deploy")
if err != nil {
return fmt.Errorf("Error getting security context: %w", err)
}

values := &AppValues{
Global: GlobalValues{
Annotations: globalAnnotations,
Expand All @@ -407,7 +412,8 @@ func TriggerSchedulerDeploy(scheduler string, appName string, imageTag string) e
PrimaryPort: primaryPort,
PrimaryServicePort: primaryServicePort,
},
Secrets: map[string]string{},
Secrets: map[string]string{},
SecurityContext: securityContext,
},
Processes: map[string]ProcessValues{},
}
Expand Down Expand Up @@ -1228,6 +1234,11 @@ func TriggerSchedulerRun(scheduler string, appName string, envCount int, args []
}
}

securityContext, err := getSecurityContext(appName, "run")
if err != nil {
return fmt.Errorf("Error getting security context: %w", err)
}

workingDir := common.GetWorkingDir(appName, image)
job, err := templateKubernetesJob(Job{
AppName: appName,
Expand All @@ -1243,6 +1254,7 @@ func TriggerSchedulerRun(scheduler string, appName string, envCount int, args []
Namespace: namespace,
ProcessType: processType,
RemoveContainer: rmContainer,
SecurityContext: securityContext,
WorkingDir: workingDir,
})
if err != nil {
Expand Down
Loading
Loading