├── Docker └── harborGetImages.go ├── GoHub ├── README.md └── main.go ├── K8s小工具 └── K8s_PodStatus.go ├── README.md └── logAgent ├── kafka └── kafka.go ├── main.go └── taillog └── taillog.go /Docker/harborGetImages.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "io/ioutil" 7 | "net/http" 8 | ) 9 | 10 | const ( 11 | HarborDN = "www.dqzboy.com" // 填入访问域名或IP 12 | HarborAddress = "https://" + HarborDN // Harbor的URL地址(需要带前缀http或者https) 13 | HarborUser = "admin" // 登录Harbor的用户 14 | HarborPassword = "Harbor123456" // 登录Harbor的用户密码 15 | ) 16 | 17 | func main() { 18 | projects := []string{"public"} // 项目列表,可以添加多个项目 19 | 20 | for _, project := range projects { 21 | imageNames, err := getRepositoryNames(project) 22 | if err != nil { 23 | fmt。Printf("Error getting repository names for project %s: %v\n", project, err) 24 | continue 25 | } 26 | 27 | for _, imageName := range imageNames { 28 | imageTags, err := getTagsForRepository(project, imageName) 29 | if err != nil { 30 | fmt。Printf("Error getting tags for image %s in project %s: %v\n", imageName, project, err) 31 | continue 32 | } 33 | 34 | for _, tag := range imageTags { 35 | fmt。Printf("%s/%s:%s\n", HarborDN, imageName, tag) 36 | } 37 | } 38 | } 39 | } 40 | 41 | func getRepositoryNames(project string) ([]string, error) { 42 | url := fmt。Sprintf("%s/api/v2.0/projects/%s/repositories", HarborAddress, project) 43 | response, err := sendRequest(url) 44 | if err != nil { 45 | return nil, err 46 | } 47 | 48 | var data []map[string]interface{} 49 | if err := json。Unmarshal(response, &data); err != nil { 50 | return nil, err 51 | } 52 | 53 | var names []string 54 | for _, repo := range data { 55 | name, ok := repo["name"]。(string) 56 | if ok { 57 | names = append(names, name) 58 | } 59 | } 60 | 61 | return names, nil 62 | } 63 | 64 | func getTagsForRepository(project, imageName string) ([]string, error) { 65 | url := fmt。Sprintf("%s/v2/%s/tags/list", HarborAddress, imageName) 66 | response, err := sendRequest(url) 67 | if err != nil { 68 | return nil, err 69 | } 70 | 71 | var data map[string]interface{} 72 | if err := json。Unmarshal(response, &data); err != nil { 73 | return nil, err 74 | } 75 | 76 | tagsInterface, ok := data["tags"]。([]interface{}) 77 | if !ok { 78 | return nil, fmt。Errorf("Tags not found in response") 79 | } 80 | 81 | var tags []string 82 | for _, tag := range tagsInterface { 83 | tagStr, ok := tag。(string) 84 | if ok { 85 | tags = append(tags, tagStr) 86 | } 87 | } 88 | 89 | return tags, nil 90 | } 91 | 92 | func sendRequest(url string) ([]byte, error) { 93 | req, err := http。NewRequest("GET", url, nil) 94 | if err != nil { 95 | return nil, err 96 | } 97 | 98 | req。SetBasicAuth(HarborUser, HarborPassword) 99 | req。Header。Set("Content-Type", "application/json") 100 | 101 | client := &http。Client{} 102 | resp, err := client。Do(req) 103 | if err != nil { 104 | return nil, err 105 | } 106 | defer resp。Body。Close() 107 | 108 | body, err := ioutil。ReadAll(resp。Body) 109 | if err != nil { 110 | return nil, err 111 | } 112 | 113 | if resp。StatusCode != http。StatusOK { 114 | return nil, fmt。Errorf("Request failed with status code %d", resp。StatusCode) 115 | } 116 | 117 | return body, nil 118 | } 119 | -------------------------------------------------------------------------------- /GoHub/README.md: -------------------------------------------------------------------------------- 1 | ## 简易版上传文件至阿里云OSS的小工具 2 | ### 1、首先在自己项目中创建etc目录并创建一个`.secret.env`文件 3 | ### 2、将阿里云账号的AccessKey以及OSS ENDPOINT添加进去 4 | ``` 5 | export ALI_AK="AccessKey ID" 6 | export ALI_SK="AccessKey Secret" 7 | export ALI_OSS_ENDPOINT="Endpoint" 8 | ``` 9 | ### 3、修改main.go代码中的BucketName为自己的Bucket 10 | ### 4、build之前先执行`source etc/.secret.env` 11 | ![gohub01](https://user-images.githubusercontent.com/42825450/148933882-ebf2acc1-0a8e-4cd6-afd0-d4b0daf764c9.jpeg) 12 | ![gohub02](https://user-images.githubusercontent.com/42825450/148933889-2ad1fcb3-cd1d-4c0b-91f1-60fb6d1104ef.jpeg) 13 | -------------------------------------------------------------------------------- /GoHub/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "github.com/aliyun/aliyun-oss-go-sdk/oss" 7 | "os" 8 | ) 9 | 10 | var ( 11 | conf = NewDefaultConfig() 12 | ) 13 | 14 | func NewDefaultConfig() *Config { 15 | return &Config{ 16 | //这里填写上传到Bucket的名称 17 | BucketName: "dqzboy", 18 | } 19 | } 20 | 21 | type Config struct { 22 | Endpoint string 23 | AK string 24 | SK string 25 | BucketName string 26 | } 27 | 28 | func (c *Config) Validate() error { 29 | if c.Endpoint == "" { 30 | return fmt.Errorf("OSS Endpoint 必须") 31 | } 32 | if c.AK == "" { 33 | return fmt.Errorf("AccessKey ID 必须") 34 | } 35 | if c.SK == "" { 36 | return fmt.Errorf("AccessKey Secret 必须") 37 | } 38 | return nil 39 | } 40 | 41 | func LoadConfigFromEnv() { 42 | conf.Endpoint = os.Getenv("ALI_OSS_ENDPOINT") 43 | conf.AK = os.Getenv("ALI_AK") 44 | conf.SK = os.Getenv("ALI_SK") 45 | } 46 | 47 | func UploadFile(filename string) (downloadURL string, err error) { 48 | client, err := oss.New(conf.Endpoint, conf.AK, conf.SK) 49 | if err != nil { 50 | err = fmt.Errorf("new client error, %s", err) 51 | return 52 | } 53 | 54 | bucket, err := client.Bucket(conf.BucketName) 55 | if err != nil { 56 | err = fmt.Errorf("get bucket %s error, %s", conf.BucketName, err) 57 | return 58 | } 59 | 60 | err = bucket.PutObjectFromFile(filename, filename) 61 | if err != nil { 62 | err = fmt.Errorf("upload file %s error, %s", filename, err) 63 | return 64 | } 65 | 66 | // 生成下载链接 67 | return bucket.SignURL(filename, oss.HTTPGet, 60*60*24*3) 68 | } 69 | 70 | //定义文件变量 71 | var ( 72 | fileName string 73 | help bool 74 | ) 75 | 76 | //声明CLI的参数 77 | func init() { 78 | flag.StringVar(&fileName, "f","","请输入需要上传的文件的路径") 79 | flag.BoolVar(&help,"help",false,"打印本工具的使用说明") 80 | } 81 | 82 | //命令执行 帮助提示 83 | func usage() { 84 | fmt.Fprintf(os.Stderr, `cloud-station version: 0.0.1 85 | Usage: cloud-station [-h] -f 86 | Options: 87 | `) 88 | //如果选项错误,返回默认提示信息 89 | flag.PrintDefaults() 90 | } 91 | 92 | // LoadArgsFromCLI 负责接收用户传入的参数 93 | func LoadArgsFromCLI() { 94 | //通过标准库flag parse解析CLI参数 95 | flag.Parse() 96 | //打印说明信息 97 | if help { 98 | usage() 99 | os.Exit(0) 100 | } 101 | } 102 | 103 | func main() { 104 | LoadConfigFromEnv() 105 | 106 | //校验配置 107 | if err := conf.Validate();err != nil { 108 | fmt.Println(err) 109 | os.Exit(1) 110 | } 111 | 112 | //接收用户参数 113 | LoadArgsFromCLI() 114 | //上传文件 115 | downloadURL, err := UploadFile(fileName) 116 | if err != nil { 117 | fmt.Println(err) 118 | os.Exit(2) 119 | } 120 | 121 | //正常退出 122 | fmt.Printf("文 件: %s 上传成功\n", fileName) 123 | 124 | // 打印下载链接 125 | fmt.Printf("下载链接: %s\n", downloadURL) 126 | fmt.Println("\n注意: 文件下载有效期为1天, 保存时间为3天, 请及时下载") 127 | os.Exit(0) 128 | } 129 | -------------------------------------------------------------------------------- /K8s小工具/K8s_PodStatus.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "log" 7 | "net/smtp" 8 | "os" 9 | "strconv" 10 | "strings" 11 | "time" 12 | 13 | "k8s.io/apimachinery/pkg/api/errors" 14 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 15 | "k8s.io/client-go/kubernetes" 16 | "k8s.io/client-go/rest" 17 | "k8s.io/client-go/tools/clientcmd" 18 | ) 19 | 20 | const ( 21 | podNamespace = "default" // 设置 Pod 所在的 Namespace 22 | ) 23 | 24 | func main() { 25 | // 创建 Kubernetes 的客户端 26 | kubeconfig := os.Getenv("KUBECONFIG") 27 | config, err := clientcmd.BuildConfigFromFlags("", kubeconfig) 28 | if err != nil { 29 | log.Fatalf("Failed to build K8s config: %v", err) 30 | } 31 | clientset, err := kubernetes.NewForConfig(config) 32 | if err != nil { 33 | log.Fatalf("Failed to create K8s client: %v", err) 34 | } 35 | 36 | // 创建邮件通知的发送函数 37 | sendEmail := func(msg string) { 38 | from := "sender@example.com" 39 | password := "password" 40 | to := []string{"recipient@example.com"} 41 | 42 | auth := smtp.PlainAuth("", from, password, "smtp.example.com") 43 | 44 | err := smtp.SendMail("smtp.example.com:587", auth, from, to, []byte(msg)) 45 | if err != nil { 46 | log.Printf("Failed to send email: %v", err) 47 | } else { 48 | log.Println("Email notification sent") 49 | } 50 | } 51 | 52 | // 定义发送邮件的时间间隔 53 | emailInterval := time.Hour 54 | 55 | // 无限循环检查 Pod 状态并发送邮件通知 56 | for { 57 | // 获取 Pod 列表 58 | pods, err := clientset.CoreV1().Pods(podNamespace).List(context.Background(), metav1.ListOptions{}) 59 | if err != nil { 60 | log.Printf("Failed to list Pods: %v", err) 61 | continue 62 | } 63 | 64 | // 统计 Pod 数量和失败的 Pod 数量 65 | podCount := len(pods.Items) 66 | failedCount := 0 67 | var failedPods []string 68 | for _, pod := range pods.Items { 69 | if pod.Status.Phase != "Running" { 70 | failedCount++ 71 | failedPods = append(failedPods, pod.Name) 72 | } 73 | } 74 | 75 | // 判断是否有失败的 Pod 76 | if failedCount > 0 { 77 | // 发送邮件通知 78 | subject := fmt.Sprintf("Alert: %d/%d Pods have failed", failedCount, podCount) 79 | body := fmt.Sprintf("Failed Pods: %s", strings.Join(failedPods, ", ")) 80 | 81 | msg := fmt.Sprintf("From: %s\nSubject: %s\n\n%s", "sender@example.com", subject, body) 82 | sendEmail(msg) 83 | 84 | // 等待指定的时间间隔后再次检查 85 | time.Sleep(emailInterval) 86 | continue 87 | } 88 | 89 | // 如果没有失败的 Pod,则等待 1 分钟后再次检查 90 | time.Sleep(time.Minute) 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Go项目实践 2 | ### 1、本项目存储个人实践源代码 3 | ### 2、大家可自行进行下载 4 | -------------------------------------------------------------------------------- /logAgent/kafka/kafka.go: -------------------------------------------------------------------------------- 1 | package kafka 2 | 3 | import ( 4 | "fmt" 5 | "github.com/Shopify/sarama" 6 | ) 7 | 8 | // 专门往kafka写日志的模块 9 | var ( 10 | client sarama.SyncProducer //声明一个全局的连接kafka的生产者 11 | 12 | ) 13 | 14 | // Init 初始化 15 | func Init(addrs []string) (err error) { 16 | config := sarama.NewConfig() 17 | //tailf 包使用 18 | config.Producer.RequiredAcks = sarama.WaitForAll //WaitForAll等待所有节点响应 19 | config.Producer.Partitioner = sarama.NewHashPartitioner //新选出一个partition 20 | config.Producer.Return.Successes = true //成功发送的消息将在succcess channel返回 21 | 22 | //连接kafka 23 | client, err = sarama.NewSyncProducer(addrs, config) 24 | if err != nil { 25 | fmt.Println("producer closed, err:", err) 26 | return 27 | } 28 | return 29 | } 30 | 31 | func SendToKafka(topic, data string) { 32 | //构造一个消息 33 | msg := &sarama.ProducerMessage{} 34 | msg.Topic = topic //topic名称 35 | msg.Value = sarama.StringEncoder(data) //使用sarama.StringEncoder序列化 36 | 37 | //发送到kafka 38 | pid, offset, err := client.SendMessage(msg) 39 | if err != nil { 40 | fmt.Println("sed msg failed, err:", err) 41 | return 42 | } 43 | fmt.Printf("pid:%v offset:%v\n", pid, offset) 44 | } 45 | -------------------------------------------------------------------------------- /logAgent/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "logagent/kafka" 6 | "logagent/taillog" 7 | "time" 8 | ) 9 | 10 | func run() { 11 | //1、读取日志 12 | for { 13 | select { 14 | case line := <-taillog.ReadChan(): 15 | //2、发送kafka 16 | kafka.SendToKafka("web_log", line.Text) 17 | default: 18 | time.Sleep(time.Second) 19 | } 20 | } 21 | } 22 | 23 | //logAgent入口 24 | func main() { 25 | //1、初始化kafka连接 26 | err := kafka.Init([]string{"192.168.66.10:9092"}) 27 | if err != nil { 28 | fmt.Printf("Kafka initialization failed, err:%v\n", err) 29 | return 30 | } 31 | fmt.Println("Kafka initialization succeeded") 32 | //2、收集日志 33 | err = taillog.Init("./my.log") 34 | if err != nil { 35 | fmt.Printf("taillog initialization failed,err:%v\n", err) 36 | return 37 | } 38 | fmt.Println("tailLog initialization succeeded") 39 | run() 40 | } 41 | -------------------------------------------------------------------------------- /logAgent/taillog/taillog.go: -------------------------------------------------------------------------------- 1 | package taillog 2 | 3 | import ( 4 | "fmt" 5 | "github.com/hpcloud/tail" 6 | ) 7 | 8 | var ( 9 | tailObj *tail.Tail 10 | LogChan chan string 11 | ) 12 | 13 | // Init 专门从日志文件收集日志的模块 14 | func Init(fileName string) (err error) { 15 | config := tail.Config{ 16 | ReOpen: true, //重新打开,日志切割 17 | Follow: true, //是否跟随上次关闭的文件 18 | Location: &tail.SeekInfo{Offset: 0, Whence: 2}, //从文件哪个地方开始读 19 | MustExist: false, //文件不存在不报错 20 | Poll: true, 21 | } 22 | tailObj, err = tail.TailFile(fileName, config) 23 | if err != nil { 24 | fmt.Println("tail file failed, err:", err) 25 | return 26 | } 27 | return 28 | } 29 | 30 | func ReadChan() <-chan *tail.Line { 31 | return tailObj.Lines 32 | } 33 | --------------------------------------------------------------------------------