发布一个k8s部署视频:https://edu.csdn.net/course/detail/26967
课程内容:各种k8s部署方式。包括minikube部署,kubeadm部署,kubeasz部署,rancher部署,k3s部署。包括开发测试环境部署k8s,和生产环境部署k8s。
腾讯课堂连接地址https://ke.qq.com/course/478827?taid=4373109931462251&tuin=ba64518
第二个视频发布 https://edu.csdn.net/course/detail/27109
腾讯课堂连接地址https://ke.qq.com/course/484107?tuin=ba64518
介绍主要的k8s资源的使用配置和命令。包括configmap,pod,service,replicaset,namespace,deployment,daemonset,ingress,pv,pvc,sc,role,rolebinding,clusterrole,clusterrolebinding,secret,serviceaccount,statefulset,job,cronjob,podDisruptionbudget,podSecurityPolicy,networkPolicy,resourceQuota,limitrange,endpoint,event,conponentstatus,node,apiservice,controllerRevision等。
第三个视频发布:https://edu.csdn.net/course/detail/27574
详细介绍helm命令,学习helm chart语法,编写helm chart。深入分析各项目源码,学习编写helm插件
第四个课程发布:https://edu.csdn.net/course/detail/28488
本课程将详细介绍k8s所有命令,以及命令的go源码分析,学习知其然,知其所以然
————————————————
//创建auth命令
func NewCmdAuth(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command {
// Parent command to which all subcommands are added.
cmds := &cobra.Command{//创建cobra命令
Use: "auth",
Short: "Inspect authorization",
Long: `Inspect authorization`,
Run: cmdutil.DefaultSubCommandRun(streams.ErrOut),
}
cmds.AddCommand(NewCmdCanI(f, streams))//添加can-i子命令
cmds.AddCommand(NewCmdReconcile(f, streams))//添加reconcile子命令
return cmds
}
type CanIOptions struct {//can-i结构体
AllNamespaces bool
Quiet bool
NoHeaders bool
Namespace string
AuthClient authorizationv1client.AuthorizationV1Interface
DiscoveryClient discovery.DiscoveryInterface
Verb string
Resource schema.GroupVersionResource
NonResourceURL string
Subresource string
ResourceName string
List bool
genericclioptions.IOStreams
}
//创建can-i命令
func NewCmdCanI(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command {
o := &CanIOptions{//初始化结构体
IOStreams: streams,
}
cmd := &cobra.Command{//创建cobra命令
Use: "can-i VERB [TYPE | TYPE/NAME | NONRESOURCEURL]",
DisableFlagsInUseLine: true,
Short: "Check whether an action is allowed",
Long: canILong,
Example: canIExample,
Run: func(cmd *cobra.Command, args []string) {
cmdutil.CheckErr(o.Complete(f, args))//准备
cmdutil.CheckErr(o.Validate())//校验
var err error
if o.List {//如果指定--list
err = o.RunAccessList()//运行list
} else {
var allowed bool
allowed, err = o.RunAccessCheck()//运行check
if err == nil {
if !allowed {
os.Exit(1)
}
}
}
cmdutil.CheckErr(err)
},
}
cmd.Flags().BoolVarP(&o.AllNamespaces, "all-namespaces", "A", o.AllNamespaces, "If true, check the specified action in all namespaces.")//all-namespaces选项
cmd.Flags().BoolVarP(&o.Quiet, "quiet", "q", o.Quiet, "If true, suppress output and just return the exit code.")//quiet选项
cmd.Flags().StringVar(&o.Subresource, "subresource", o.Subresource, "SubResource such as pod/log or deployment/scale")//subresource选项
cmd.Flags().BoolVar(&o.List, "list", o.List, "If true, prints all allowed actions.")//list选项
cmd.Flags().BoolVar(&o.NoHeaders, "no-headers", o.NoHeaders, "If true, prints allowed actions without headers")//no-headers选项
return cmd
}
//准备
func (o *CanIOptions) Complete(f cmdutil.Factory, args []string) error {
if o.List {//如果指定了--list
if len(args) != 0 {//参数不等于0个报错
return errors.New("list option must be specified with no arguments")
}
} else {
if o.Quiet {//指定了quiet
o.Out = ioutil.Discard//设置out
}
switch len(args) {//判断参数个数
case 2://为2个
o.Verb = args[0]//第0个位动作
if strings.HasPrefix(args[1], "/") {//第1个参数有/开头
o.NonResourceURL = args[1]//设置非资源url
break
}
resourceTokens := strings.SplitN(args[1], "/", 2)//用/分割
restMapper, err := f.ToRESTMapper()//获取restMapper
if err != nil {
return err
}
o.Resource = o.resourceFor(restMapper, resourceTokens[0])//设置资源
if len(resourceTokens) > 1 {
o.ResourceName = resourceTokens[1]//设置资源名称
}
default:
return errors.New("you must specify two or three arguments: verb, resource, and optional resourceName")//报错
}
}
var err error
client, err := f.KubernetesClientSet()//获取clientset
if err != nil {
return err
}
o.AuthClient = client.AuthorizationV1()//从clientset获取authClient
o.DiscoveryClient = client.Discovery()//从clientset获取discoberyClient
o.Namespace = ""//设置namespace为空
if !o.AllNamespaces {//没有指定all-namespaces
o.Namespace, _, err = f.ToRawKubeConfigLoader().Namespace()//设置namespace
if err != nil {
return err
}
}
return nil
}
//校验
func (o *CanIOptions) Validate() error {
if o.List {//指定了list
if o.Quiet || o.AllNamespaces || o.Subresource != "" {//list不能和这三个同时指定
return errors.New("list option can't be specified with neither quiet, all-namespaces nor subresource options")
}
return nil
}
if o.NonResourceURL != "" {//指定了非资源url
if o.Subresource != "" {//不能同时指定子资源
return fmt.Errorf("--subresource can not be used with NonResourceURL")
}
if o.Resource != (schema.GroupVersionResource{}) || o.ResourceName != "" {//不能同时指定资源名称
return fmt.Errorf("NonResourceURL and ResourceName can not specified together")
}
} else if !o.Resource.Empty() && !o.AllNamespaces && o.DiscoveryClient != nil {
if namespaced, err := isNamespaced(o.Resource, o.DiscoveryClient); err == nil && !namespaced {//判断资源是否集群范围
if len(o.Resource.Group) == 0 {//输出告警
fmt.Fprintf(o.ErrOut, "Warning: resource '%s' is not namespace scoped\n", o.Resource.Resource)
} else {
fmt.Fprintf(o.ErrOut, "Warning: resource '%s' is not namespace scoped in group '%s'\n", o.Resource.Resource, o.Resource.Group)
}
}
}
if o.NoHeaders {//no-headers必须和list同时指定
return fmt.Errorf("--no-headers cannot be set without --list specified")
}
return nil
}
//执行list
func (o *CanIOptions) RunAccessList() error {
sar := &authorizationv1.SelfSubjectRulesReview{//创建SelfSubjectRulesReview
Spec: authorizationv1.SelfSubjectRulesReviewSpec{
Namespace: o.Namespace,
},
}
response, err := o.AuthClient.SelfSubjectRulesReviews().Create(sar)//应用SelfSubjectRulesReview到服务端
if err != nil {
return err
}
return o.printStatus(response.Status)//输出结果
}
//执行check
func (o *CanIOptions) RunAccessCheck() (bool, error) {
var sar *authorizationv1.SelfSubjectAccessReview//定义SelfSubjectAccessReview
if o.NonResourceURL == "" {//非资源url为空
sar = &authorizationv1.SelfSubjectAccessReview{//创建SelfSubjectAccessReview
Spec: authorizationv1.SelfSubjectAccessReviewSpec{
ResourceAttributes: &authorizationv1.ResourceAttributes{
Namespace: o.Namespace,
Verb: o.Verb,
Group: o.Resource.Group,
Resource: o.Resource.Resource,
Subresource: o.Subresource,
Name: o.ResourceName,
},
},
}
} else {
sar = &authorizationv1.SelfSubjectAccessReview{//创建SelfSubjectAccessReview
Spec: authorizationv1.SelfSubjectAccessReviewSpec{
NonResourceAttributes: &authorizationv1.NonResourceAttributes{
Verb: o.Verb,
Path: o.NonResourceURL,
},
},
}
}
response, err := o.AuthClient.SelfSubjectAccessReviews().Create(sar)//应用SelfSubjectAccessReview到服务端
if err != nil {
return false, err
}
if response.Status.Allowed {//结果为allowed打印yes
fmt.Fprintln(o.Out, "yes")
} else {
fmt.Fprint(o.Out, "no")//打印no
if len(response.Status.Reason) > 0 {//打印reason
fmt.Fprintf(o.Out, " - %v", response.Status.Reason)
}
if len(response.Status.EvaluationError) > 0 {//打印EvaluationError
fmt.Fprintf(o.Out, " - %v", response.Status.EvaluationError)
}
fmt.Fprintln(o.Out)
}
return response.Status.Allowed, nil
}